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


    Una biblioteca de funciones para programar videojuegos.

        Por Shawn Hargreaves, 15 de Diciembre del 2001.

      Lea en el fichero AUTHORS un listado completo de los que han
      contribudo a Allegro, y en el fichero AUTORES un listado
      completo de los que han contribudo a la traduccin de Allegro.




#include <std_disclaimer.h>

   "No me responsabilizo de ningn efecto, adverso u otro que este cdigo
    pueda tener sobre usted, su ordenador, su salud, su perro, o cualquier
    otra cosa que pueda imaginar. Uselo bajo su propio responsabilidad."



===========================================
============ 00 Usando Allegro ============
===========================================

Puede leer en readme.txt una introduccin general, detalles de copyright e
informacin sobre cmo instalar Allegro y enlazar su programa con la
biblioteca.

int install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)());
   Inicializa Allegro. Debe llamar a esta funcin o a allegro_init() antes de
   hacer otra cosa que no sea usar las rutinas Unicode. Si quiere usar un
   formato de texto diferente al UTF-8, puede ajustarlo con set_uformat()
   antes de llamar a esta funcin. Los identificadores de sistema disponibles
   (system_id) variarn dependiendo de la plataforma utilizada, pero casi
   siempre querr usar SYSTEM_AUTODETECT. Alternativamente, SYSTEM_NONE
   instalar una versin reducida de Allegro que no intentar realizar
   accesos directos al hardware ni operaciones que sean particulares a una
   plataforma especfica: esto puede resultar til para situaciones en las
   que solamente quiera manipular bitmaps de memoria, como en una utilidad
   que maneje ficheros de datos o las funciones de interfaz con el GDI de
   Windows. Los parmetros errno_ptr y atexit_ptr deben apuntar a la variable
   errno y la funcin atexit() de su librera C respectivamente. Estos
   parmetros son requeridos ya que cuando Allegro es enlazado como una DLL
   no tiene acceso directo a los datos locales de su librera C. atexti_ptr
   puede ser NULL, en cuyo caso ser su responsabilidad llamar allegro_exit
   manualmente. Por ahora esta funcin siempre devuelve cero. Si no se puede
   usar ningn driver de sistema, el programa ser abortado.

int allegro_init();
   Macro que inicia la librera Allegro. Esta funcin es equivalente a la
   llamada install_allegro(SYSTEM_AUTODETECT, &errno, atexit).

void allegro_exit();
   Cierra el sistema Allegro. Esto incluye devolver el sistema al modo texto
   y desinstalar todas las rutinas de ratn, teclado o temporizacin que
   estuviesen instaladas. Normalmente no tiene que molestarse en hacer una
   llamada explcita a esta funcin, ya que allegro_init() la instala como
   una funcin atexit(), por lo que ser llamada automticamente cuando su
   programa finalice.

extern char allegro_id[];
   Cadena de texto que contiene la fecha y nmero de versin de Allegro, en
   caso de que quiera ensear estos datos en alguna parte.

extern char allegro_error[ALLEGRO_ERROR_SIZE];
   Cadena de texto usada por set_gfx_mode() e install_sound() para indicar
   mensajes de error. Si stas funciones fallan y quiere decirle al usuario
   porqu, ste es el lugar en el que se encuentra una descripcin del
   problema.

extern int os_type;
   Variable ajustada por allegro_init() a uno de los siguientes valores:

      OSTYPE_UNKNOWN    - desconocido, o MSDOS normal
      OSTYPE_WIN3       - Windows 3.1 o versiones anteriores
      OSTYPE_WIN95      - Windows 95
      OSTYPE_WIN98      - Windows 98
      OSTYPE_WINME      - Windows ME
      OSTYPE_WINNT      - Windows NT
      OSTYPE_WIN2000    - Windows 2000
      OSTYPE_WINXP      - Windows XP
      OSTYPE_OS2        - OS/2
      OSTYPE_WARP       - OS/2 Warp 3
      OSTYPE_DOSEMU     - Linux DOSEMU
      OSTYPE_OPENDOS    - Caldera OpenDOS
      OSTYPE_LINUX      - Linux
      OSTYPE_FREEBSD    - FreeBSD
      OSTYPE_UNIX       - variante Unix desconocida
      OSTYPE_BEOS       - BeOS
      OSTYPE_QNX        - QNX
      OSTYPE_MACOS      - MacOS

extern int os_version;
extern int os_revision;
   La versin mayor y menor del Sistema Operativo usado. Ajustado por
   allegro_init(). Si Allegro por alguna razn no es capaz de obtener la
   versin de su Sistema Operativo, os_version y os_revision valdrn -1. Por
   ejemplo: bajo Win98 SE (v4.10.2222) os_version valdr 4 y os_revision
   valdr 10.

extern int os_multitasking;
   Ajustado por allegro_init() a TRUE o FALSE dependiendo de si su Sistema
   Operativo es multitarea o n.

void allegro_message(char *msg, ...);
   Muestra un mensaje usando una cadena con formato printf(). Esta funcin
   slo debe ser utilizada cuando no est en un modo grfico, es decir, antes
   de llamar a set_gfx_mode() o despus de llamar a set_gfx_mode(GFX_TEXT).
   En plataformas que tengan una consola en modo texto (DOS, Unix y BeOS),
   mostrar la cadena en la consola reduciendo los carcteres acentuados a
   aproximaciones en 7 bits de cdigos ASCII, evitando en lo posible los
   problemas con las diferentes pginas de cdigos. Bajo Windows, el mensaje
   aparecer en un ventana de mensajes.

void set_window_title(const char *name);
   En las plataformas que sean capaces de ello, esta rutina cambia el ttulo
   de la ventana utilizada para su programa. Tenga en cuenta que Allegro no
   es capaz de modificar el ttulo de la ventana cuando ejecute una ventana
   DOS en Windows.

int set_window_close_button(int enable);
   En las plataformas que sean capaces de ello, esta rutina activa o
   desactiva el botn de cerrar ventana de su programa Allegro. Si lo
   desea, puede llamar esta rutina antes de que la ventana sea creada. Si el
   botn de cerrar ventana es desactivado con xito, esta funcin devolver
   cero.

   En plataformas en las que el botn de cerrado no existe o no puede ser
   desactivado, la funcin devolver -1. Si esto ocurre, quizs le interese
   usar set_window_close_hook() para manejar manualmente el evento de cierre
   de la ventana.

   Cuando active el botn de cierre, la funcin devolver el mismo valor
   que devolvi su plataforma al desactivarlo. Esto significa que devolver
   distinto de cero si el botn no se puede desacivar, a pesar de que no
   est intentando desactivarlo.

   Tenga en cuenta que Allegro no puede manipular el botn de cerrado de una
   ventana DOS bajo Windows.

void set_window_close_hook(void (*proc)());
   En las plataformas que tengan botn de cierre, esta rutina instala una
   funcin de enganche en el evento de cierre. En otras palabras, cuando el
   usuario pinche en el botn que cerrara la ventana de su programa, se
   llamar a la funcin que especifique aqu. Puede usar esta funcin para
   mostrar un dilogo ofreciendo salvar los datos o verificar que el usuario
   realmente desea salir, o puede usarla para salvar los datos, liberar
   memoria y salir.

   Esta funcin generalmente no debera intentar salir del programa o salvar
   datos por s misma. Esta funcin podra ser llamada en cualquier momento,
   y hay peligro de que los datos que intente salvar sean invlidos en ese
   momento. Por eso, debera activar una variable durante esta funcin, y
   verificar esta variable regularmente en su programa principal.

   Pase NULL a esta funcin para recuperar la funcionalidad por defecto del
   botn de cierre. En Windows y BeOS, el siguiente mensaje aparecer:

      Aviso: forzar la finalizacin del programa puede ocasionar prdidas
      de datos y resultados inesperados. Es preferible que use el comando
      de salir dentro de la ventana.

      Desea continuar de todas maneras?

      [Si] [No]

   Este mensaje ser traducido al lenguaje seleccionado si hay una
   traduccin dispobible en language.dat (vea get_config_text()).

   Si el usuario selecciona [Si], el programa finalizar inmediatamente
   en el mismo estilo que cuando el usuario pulsa Ctrl+Alt+End (vea
   three_finger_flag).

   En otros sistemas operativos, el programa saldr inmediatamente sin
   preguntar nada al usuario.

   Tenga en cuenta que Allegro no puede interceptar el botn de cierre de
   una ventana DOS bajo Windows.
 
int desktop_color_depth();
   En plataformas que pueden ejecutar programas de Allegro en una ventana
   de un escritorio existente, devuelve la profundidad de color usada por
   el escritorio en ese momento (su programa posiblemente correr ms si
   usa la misma profundidad de color. En plataformas donde esta
   informacin no es disponible o no tiene sentido, devuelve cero.

int get_desktop_resolution(int *width, int *height);
   En plataformas que pueden ejecutar programas de Allegro en una ventana
   de un escritorio existente, permite obtener la resolucin actual usada
   por el escritorio (ej: le itneresar llamar a esta funcin antes de crear
   una gran ventana, porque en algunos drivers de modo ventana, sta no
   puede ser creada si es mayor que el escritorio). Devuelve cero si hubo
   xito, o un nmero negativo si la informacin no est disponible o no es
   aplicable a su situacin, en cuyo caso los valores almacenados en width
   y heigth sern indefinidos.

void yield_timeslice();
   En los sistemas que lo soportan, libera el resto de la "rebanada
   temporal" (timeslice) que la CPU le haba asignado. Esta opcin tambin
   es conocida como "prtate bien con la multitarea".

void check_cpu();
   Detecta el tipo de CPU, asignando valores a las siguientes variables
   globales. Normalmente no necesita llamar a esta funcin, ya que
   allegro_init() lo har por usted.

extern char cpu_vendor[];
   Contiene el nombre del proveedor de la CPU si ste es conocido. En
   plataformas no-Intel, contiene una cadena vaca.

extern int cpu_family;
   Contiene el tipo de CPU Intel, en las CPUs donde sea aplicable: 3=386,
   4=486, 5=Pentium, 6=PPro, etc.

extern int cpu_model;
   Contiene el submodelo de una CPU Intel, en las CPUs donde sea aplicable.
   En un 486 (cpu_family=4), cero o uno indica un chip DX, 2 un SX, 3 indica
   la presencia de un coprocesador matemtico (486 SX + 487  486 DX), 4 un
   SL, 5 un SX2, 7 un DX2 write-back enhanced, 8 un DX4 o un overdrive DX4,
   14 un Cyrix y 15 desconocido. En un chip Pentium (cpu_family=5), 1 indica
   un Pentium (510\66, 567\66), 2 un Pentium P54C, 3 un procesador Pentium
   overdrive, 5 un Pentium overdrive para IntelDX4, 14 un Cyrix y 15
   desconocido.

extern int cpu_capabilities;
   Contiene bits de la CPU que indican qu caractersticas estn disponibles.
   Los bits pueden ser una combinacin de:

      CPU_ID       - Indica que la instruccin "cpuid" est disponible.
                     Si este bit est activo, entonces todas las variables
                     CPU de Allegro son fiables al 100%, en caso contrario
                     podra haber fallos.
      CPU_FPU      - Hay disponible una FPU x87.
      CPU_MMX      - Conjunto de instrucciones Intel MMX  disponible.
      CPU_MMXPLUS  - Conjunto de instrucciones Intel MMX+ disponible.
      CPU_SSE      - Conjunto de instrucciones Intel SSE  disponible.
      CPU_SSE2     - Conjunto de instrucciones Intel SSE2 disponible.
      CPU_3DNOW    - Conjunto de instrucciones AMD 3DNow! disponible.
      CPU_ENH3DNOW - Conjunto de instrucciones AMD Enhanced 3DNow!
                     disponible.
      CPU_CMOV     - Instruccin "cmov" del Pentium Pro disponible.


   Puede verificar mltiples caractersticas haciendo una OR de los bits. Por
   ejemplo, para ver si la CPU tiene una FPU y un conjunto de instrucciones
   MMX podra hacer:

      if ((cpu_capabilities & (CPU_FPU | CPU_MMX)) == (CPU_FPU | CPU_MMX))
         printf("La CPU tiene tanto una FPU como instrucciones MMX!\n");




============================================
============ 01 Rutinas Unicode ============
============================================

Allegro puede manipular y mostrar texto usando cualquier carcter en el rango
que va de 0 a 2^32-1 (aunque por ahora grabber slo puede crear fuentes
usando carcteres hasta 2^16-1). Puede escoger entre varios tipos de formatos
de codificacin de texto, los cuales controlan la forma en la que las cadenas
son almacenadas y cmo Allegro interpreta las que usted le pase. Esta
configuracin afecta a todos los aspectos del sistema: cada vez que observe
una funcin que devuelve un puntero a carcter (char *) o que toma un puntero
a carcter como argumento, el texto utilizar el formato que se le haya
indicado a Allegro.

Por defecto, Allegro usa texto codificado en el formato UTF-8 (U_UTF8). Este
es un formato de anchura variable donde los carcteres pueden tener cualquier
tamao de 1 a 6 bytes. Lo bueno de este formato es que los carcteres de 0 a
127 pueden ser almacenados directamente, o lo que es igual, significa que es
compatible con cdigos ASCII de 7 bits ("Hola, Mundo!" es exactamente la
misma cadena en ASCII que en UTF-8). Cualquier carcter por encima del 128
como vocales acentuadas, el smbolo monetario ingls o carcteres rabes y
chinos sern codificados como una secuencia de dos o ms bytes con un valor
en el rango 128-255. Esto permite que al mostrar la cadena no se obtengan
carcteres extraos en ASCII que en realidad forman parte de la codificacin
de un carcter con diferente valor, lo que hace realmente fcil manipular
cadenas UTF-8.

Existen algunos editores de texto que entienden ficheros UTF-8, pero
alternativamente, puede escribir sus cadenas en ASCII plano o en formato
Unicode de 16 bit y luego utilizar el programa textconv (suministrado con
Allegro) para convertir el texto a UTF-8.

Si prefiere usar otros formatos de texto, Allegro permite la utilizacin de
formatos ASCII de 8 bits (U_ASCII) o Unicode de 16 bits (U_UNICODE). Adems
puede programar sus propias funciones para manejar otros formatos de texto
con Allegro (sera sencillo aadir soporte para el formato UCS-4 de 32 bits,
o el formato GB-code chino).

Tambin existe soporte limitado para pginas de cdigos alternativas de 8
bits a travs del modo U_ASCII_CP. Lo malo de este modo es que es muy lento y
no debera utilizarse para aplicaciones serias. Sin embargo, puede utilizarse
para convertir texto fcilmente entre diferentes pginas de cdigos. Por
defecto, el modo U_ASCII_CP es activado para convertir texto al formato ASCII
de 7 bits, convirtiendo las vocales acentuadas en sus equivalente (por
ejemplo, allegro_message() utiliza este modo para mostrar los mensajes en una
consola DOS). Si necesita trabajar con otras pginas de cdigos, puede
hacerlo pasando un mapeado de carcteres a la funcin set_ucodepage().

Tenga en cuenta que puede usar las rutinas Unicode antes de llamar
install_allegro() o allegro_init(). Si quiere trabajar en un formato de texto
distinto al UTF-8, lo mejor es que lo seleccione con set_uformat() antes de
llamar estas funciones.

void set_uformat(int type);
   Establece el formato de codificacin de texto a utilizar. Esta operacin
   afectar a todos las funcines de Allegro que devuelvan un puntero a
   carcter (char *) o acepten un puntero a carcter como parmetro. El
   parmetro type debe ser uno de los siguientes:

      U_ASCII     - carcteres ASCII de 8 bits de tamao fijo
      U_ASCII_CP  - pgina de cdigos alternativa de 8 bits (ver
                    set_ucodepage())
      U_UNICODE   - carcteres Unicode de 16 bits de tamao fijo
      U_UTF8      - carcteres Unicode UTF-8 de tamao variable

   Aunque es posible cambiar el formato de texto en cualquier momento, no es
   una prctica demasiado recomendable. Muchas cadenas (entre ellas los
   nombres de los drivers de hardware y algunas traducciones) son
   inicializadas en la llamada a allegro_init(), por lo tanto, si se cambia
   el formato de texto tras dicha llamada, las cadenas estarn en un formato
   diferente al seleccionado y el sistema no funcionar de forma apropiada.
   Como normal general, slo debera llamarse a set_uformat() una vez, antes
   de llamar a allegro_init(), y utilizar el formato de texto seleccionado
   durante toda la ejecucin de su programa.

int get_uformat(void);
   Devuelve el formato de codificacin de texto actualmente seleccionado.

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));
   Instala un conjunto de funciones para el manejo de un nuevo formato de
   codificacin de carcteres. El parmetro type identifica el nuevo formato,
   que debera ser una cadena de 4 carcteres como las producidas por la
   macro AL_ID(). Esta cadena ser la que se pase posteriormente a funciones
   como set_uformat() y uconvert(). Los punteros a funciones pasados como
   parmetros, son manejadores que implementan el acceso a los carcteres de
   una cadena formateada con la nueva codificacin (vea ms abajo para ms
   detalles).

void set_ucodepage(const unsigned short *table,
          const unsigned short *extras);
   Cuando se selecciona el modo U_ASCII_CP, los carcteres de 8 bits son
   convertidos a sus equivalentes en Unicode a travs de un conjunto de
   tablas. Se puede usar esta funcin para especificar un conjunto de tablas
   personalizadas que permitan la utilizacin de pginas de cdigos de 8 bits
   alternativas. El parmetro table apunta a un array de 256 enteros short
   que contienen el valor Unicode para cada carcter en la pgina de cdigos.
   El parmetro extras, si no es NULL, apunta a una lista de pares de valores
   que es utilizada para realizar la conversin inversa, es decir, reducir
   los valores Unicode a la representacin correcta dentro de la nueva
   pgina de codigos. Cada par de valores consiste en un valor Unicode
   seguido por la forma de representacin correspondiente dentro de la pgina
   de cdigos. La tabla debe finalizar con el valor cero en Unicode. Esta
   tabla permite que varios carcteres Unicode puedan representarse mediante
   un solo valor en la pgina de codigos (por ejemplo para reducir vocales
   acentuadas a ASCII de 7 bits).

int need_uconvert(const char *s, int type, int newtype);
   Dado un puntero a una cadena, el tipo de la cadena y el tipo al que se
   desea convertir, esta funcin indica si dicha conversin es necesaria. La
   conversin no es necesaria si type y newtype son el mismo tipo o son tipos
   equivalentes (por ejemplo ASCII y UTF-8 y la cadena contiene carcteres
   menores que 128). Como valor para uno de los parmetros type, se puede
   pasar U_CURRENT que representa el tipo actualmente seleccionado.

int uconvert_size(const char *s, int type, int newtype);
   Devuelve el nmero de bytes que sern necesarios para almacenar la cadena
   especificada tras una conversin al nuevo tipo, incluyendo el carcter
   terminador nulo. Los parmetros type pueden usar el valor U_CURRENT para
   indicar el tipo actualmente seleccionado.

void do_uconvert(const char *s, int type,
        char *buf, int newtype, int size);
   Convierte la cadena especificada del tipo type al tipo newtype, guardando
   como mucho size bytes en el buffer buf. Los parmetros type pueden
   utilizar el valor U_CURRENT para indicar el tipo actualmente seleccionado.

char *uconvert(const char *s, int type,
      char *buf, int newtype, int size);
   Esta es una funcin de alto nivel que sirve como ayuda para ejecutar
   do_uconvert(). Al igual que do_uconvert(), convierta la cadena
   especificada del tipo type al tipo newtype, guardando como mucho size
   bytes en el buffer buf. La ventaja que obtenemos a usar uconvert() es que
   comprueba los tipos antes de realizar la conversin, para asegurarse de
   que son tipos diferentes, no realizando conversin alguna si los tipos son
   iguales o equivalentes. Si la conversin fue realizada, devuelve un
   puntero a buf, en caso contrario, devuelve una copia de la cadena a
   convertir (s). Por lo tanto, debe usar el valor devuelto en lugar de
   asumir que la cadena ha sido movida a buf. Si buf es NULL, la cadena ser
   convertida en un buffer esttico interno. Sin embargo, debera tener
   cuidado al usar este comportamiento, ya que el buffer ser sobreescrito
   cada vez que la rutina sea invocada, por lo que no espere que los datos
   persistan tras haber hecho llamadas a otras funciones de la biblioteca.

char *uconvert_ascii(const char *s, char buf[]);
   Macro auxiliar para convertir cadenas desde ASCII al formato actual de
   codificacin. Se expande a
   uconvert(s, U_ASCII, buf, U_CURRENT, sizeof(buf)).

char *uconvert_toascii(const char *s, char buf[]);
   Macro auxiliar para convertir cadenas desde el formato actual de
   codificacin a ASCII. Se expande a
   uconvert(s, U_CURRENT, buf, U_ASCII, sizeof(buf)).

extern char empty_string[];
   No se puede fiar de que "" sea una cadena vaca vlida en todos los
   formatos de codificacin. Este bffer global contiene un nmero de ceros
   consecutivos, as que siempre ser una cadena vaca vlida, sin tener
   importancia si el programa se est ejecutando en modo ASCII, Unicode o
   UTF-8.

int ugetc(const char *s);
   Funcin auxiliar de bajo nivel para leer datos de texto en Unicode. Dado
   un puntero a una cadena en el formato de codificacin actual devuelve el
   siguiente caracter de la cadena.

int ugetx(char **s);
int ugetxc(const char **s);
   Funcin auxiliar de bajo nivel para leer datos de texto en Unicode. Dada
   la direccin de un puntero a un string en el formato de codificacin
   actual devuelve el siguiente caracter de la cadena y avanza el puntero al
   siguiente caracter.

   ugetxc es para trabajar con datos char constantes puntero a puntero.

int usetc(char *s, int c);
   Funcin auxiliar de bajo nivel para escribir datos de texto en Unicode.
   Escribe el caracter especificado en la direccin dada usando el formato
   de codificacin actual y devuelve el nmero de bytes escritos.

int uwidth(const char *s);
   Funcin auxiliar de bajo nivel para comprobar datos de texto en Unicode.
   Devuelve el nmero de bytes ocupados por el primer caracter de la cadena
   especificada en el formato de codificacin actual.

int ucwidth(int c);
   Funcin auxiliar de bajo nivel para comprobar datos de texto en Unicode.
   Devuelve el nmero de bytes que ocupara el caracter especificado en caso
   de codificarse en el formato actual.

int uisok(int c);
   Funcin auxiliar de bajo nivel para comprobar datos de texto en Unicode.
   Comprueba que el valor especificado puede ser codificado correctamente en
   en el formato actual.

int uoffset(const char *s, int index);
   Devuelve el desplazamiento en bytes desde el comienzo de la cadena hasta
   el caracter correspondiente al ndice especificado. Si el ndice es
   negativo, cuenta haca atrs desde el final de la cadena, as que un
   ndice de -1 devolver un desplazamiento al ltimo caracter.

int ugetat(const char *s, int index);
   Devuelve el valor del caracter de la cadena correspondiente al ndice
   especificado. Un parmetro indice igual a 0 devolver el primer caracter
   de la cadena. Si el ndice es negativo, cuenta hacia atrs desde el final
   de la cadena. As pues un ndice de -1 devolver el ultimo caracter de la
   cadena.

int usetat(char *s, int index, int c);
   Reemplaza el caracter del string con el ndice especificado por el valor
   c, haciendo los ajustes necesarios debido a la anchura de la variable
   (ej: si c se codifica con una anchura diferente que el valor que haba
   antes en esa posicin). Devuelve el nmero de bytes que ha sido desplazada
   la parte derecha de la cadena. Si el ndice es negativo cuenta hacia atrs
   desde el final de la cadena.

int uinsert(char *s, int index, int c);
   Inserta el caracter c en la posicin de la cadena especificada por index,
   desplazando el resto de los datos para hacer sitio. Devuelve el nmero de
   bytes que ha desplazado la parte derecha. Si el ndice es negativo cuenta
   hacia atras desde el final de la cadena.

int uremove(char *s, int index);
   Borra el caracter que hay en la posicin index de la cadena, desplazando
   el resto de los datos para llenar la posicin vaca. Devuelve el nmero de
   bytes que se ha tenido que desplazar la parte derecha de la cadena, si
   index es negativo empieza a contar desde el final de la cadena

int ustrsize(const char *s);
   Devuelve el tamao de la cadena especificada en bytes, sin incluir el
   caracter nulo finalizador de cadena.

int ustrsizez(const char *s);
   Devuelve el tamao de la cadena especificada en bytes, incluyendo el
   caracter nulo finalizador de cadena.

int uwidth_max(int type);
   Rutinas ayudantes de bajo nivel para trabajar con texto Unicode.
   Devuelven el mayor nmero de bytes que un carcter puede ocupar en el
   formato de codificacin especificado. Pase U_CURRENT para indicar el
   formato de codificacin actual.

int utolower(int c);
   Esta funcin devuelve c, convirtindola a minsculas si estaba en
   maysculas.

int utoupper(int c);
   Esta funcin devuelve c, convirtindola a maysculas si estaba en
   minsculas.
   
int uisspace(int c);
   Devuelve distinto de cero si c es carcter de espaciado, es decir, un
   retorno de carro, una nueva lnea, pgina, un tabulador, un tabulador
   vertical o un espacio.

int uisdigit(int c);
   Devuelve distinto de cero si c es un dgito.

char *ustrdup(const char *src)
   Esta funcin copia la cadena src terminada en NULL en una nueva rea de
   memoria reservada. La memoria devuelta por esta llamada debe ser liberada
   por el usuario. Devuelve NULL si no puede reservar espacio para la cadena
   duplicada.

char *_ustrdup(const char *src, void* (*malloc_func) (size_t))
   Hace lo mismo que ustrdup(), pero permite especificar al usuario su
   propia rutina para reservar memoria.

char *ustrcpy(char *dest, const char *src);
   Esta funcin copia src en dest (incluyendo el terminador de cadena NULL).
   El valor de retorno es el valor de dest.

char *ustrzcpy(char *dest, int size, const char *src);
   Esta funcin copia src en dest (incluyendo el terminador de cadena NULL),
   cuya longitud en bytes es especificada por size y que est garantizado
   que termine en carcter NULL. El valor de retoron es el valor de dest.

char *ustrcat(char *dest, const char *src);
   Esta funcin concatena src al final de dest. El valor de retorno es el
   valor de dest.

char *ustrzcat(char *dest, int size, const char *src);
   Esta funcin concatena src al final de dest, cuya longitud en bytes es
   especificada por size y que est garantizado que termine en carcter
   NULL. El valor de retorno es el valor de dest.

int ustrlen(const char *s);
   Esta funcin devuelve el nmero de carcteres de s. Tenga en cuenta que
   esto no tiene que ser igual que el tamao de la cadena en bytes.

int ustrcmp(const char *s1, const char *s2);
   Esta funcin compara s1 con s2. Devuelve cero si las cadenas son iguales,
   un nmero positivo si s1 va detrs de s2 en la secuencia ASCII apropiada,
   o negativo en caso contrario.

char *ustrncpy(char *dest, const char *src, int n);
   Esta funcin es como ustrcpy() excepto que no copiar ms de n carcteres
   de src a dest. Si src es menor en longitud que n carcteres, se aadirn
   carcteres NULL en dest hasta rellenar los n carcteres especificados.
   Note que si src es mayor que n carcteres, dest no terminar en NULL. El
   valor de retorno es el valor de dest.

char *ustrzncpy(char *dest, int size, const char *src, int n);
   Esta funcin es como ustrzcpy() excepto que no copiar ms de n
   carcteres de src a dest. Si src es menor en longitud que n carcteres,
   se aadirn carcteres NULL en dest hasta rellenar los n carcteres
   especificados. Note que est garantizado que dest acabe en carcter NULL.
   El valor de retorno es el valor de dest.

char *ustrncat(char *dest, const char *src, int n);
   Esta funcin es como `strcat' con la excepcin de que no se aadirn ms
   de n bytes de src al final de dest. Si el carcter terminador NULL es
   encontrado en src antes de haber escrito n carcteres, el carcter NULL
   ser copiado, pero no se escribirn ms carcteres. Si n carcteres son
   copiados antes de encontrar el carcter NULL, la funcin aadir
   automticamente el carcter NULL a dest, por lo que se escribirn n+1
   carcteres. El valor de retorno es dest.
   
char *ustrzncat(char *dest, int size, const char *src, int n);
   Esta funcin es como ustrszcat() con la excepcin de que no se aadirn
   ms de n carcteres de src al final de dest. Si el carcter terminador
   NULL es encontrado en src antes de haber escrito n carcteres, el
   carcter NULL ser copiado, pero no se escribirn ms carcteres. Note
   que est garantizado que dest acabe en carcter NULL. El valor de
   retorno es el valor de dest.

int ustrncmp(const char *s1, const char *s2, int n);
   Esta funcin compara hasta n carcteres de s1 con s2. Devuelve cero si
   las cadenas son iguales, un nmero positivo si s1 va detrs de s2 en la
   secuencia ASCII apropiada, o negativo en caso contrario.

int ustricmp(const char *s1, const char *s2);
   Esta funcin compara s1 con s2, ignorando las maysculas.

char *ustrlwr(char *s);
   Esta funcin sustituye todas las letras maysculas de s con minsculas.

char *ustrupr(char *s);
   Esta funcin sustituye todas las letras minsculas de s con mayscylas.

char *ustrchr(const char *s, int c);
   Esta funcin devuelve un puntero a la primera ocurrencia de c en s, o
   NULL si s no contiene c. Tenga en cuenta que si c es NULL, esta funcin
   devolver un puntero al final de la cadena.

char *ustrrchr(const char *s, int c);
   Esta funcin devuelve un puntero a la ltima ocurrencia de c en s, o NULL
   si s no contiene c.

char *ustrstr(const char *s1, const char *s2);
   Esta funcin busca la primera ocurrencia de s2 en s1. Devuelve un puntero
   dentro de s1, o NULL si s2 no fue encontrada.

char *ustrpbrk(const char *s, const char *set);
   Esta funcin encuentra el primer carcter de s que est contenido en set.
   Devuelve un puntero a la primera ocurrencia, o NULL si no se encontr
   nada.

char *ustrtok(char *s, const char *set);
   Esta funcin recupera palabras de s que estn delimitadas por carcteres
   de set. Para iniciar la bsqueda, pase la cadena que quiere analizar como
   s. Para el resto de las palabras, pase NULL en su lugar. Devuelve un
   puntero a la palabra, o NULL si no se encontr nada. Aviso: dado que
   ustrtok altera la cadena que est analizando, debe copiar siempre su
   cadena a un buffer temporal antes de analizarla. Adems, esta funcin no
   es reentrante (ej: no puede analizar dos cadenas simultneamente).

char *ustrtok_r(char *s, const char *set, char **last);
   Versin reentrante de ustrtok. El ltimo parmetro es usado para almacenar
   por dnde iba el procesado de la cadena y debe ser un puntero a una
   variable char * reservada por el usuario que no debe ser modificada
   mientras se procesa la misma cadena.

double uatof(const char *s);
   Convierte tanto como sea posible de la cadena a un nmero equivalente en
   coma flotante de doble precisin. Esta funcin es casi como `ustrtod(s,
   NULL)'. Devuelve un valor equivalente, o cero si la cadena no representa
   un nmero.

long ustrtol(const char *s, char **endp, int base);
   Esta funcin convierte la parte inicial de s a un entero con signo, el
   cual ser devuelto como un valor de tipo `long int', haciendo que *endp
   apunte al primer carcter no convertido, si endp no es un puntero nulo.
   Si el parmetro base es cero, la base es determinada buscando cosas como
   `0x', `0X', o `0' como parte inicial de la cadena, y ajusta la base a 16,
   16 u 8 respectivamente si se encuentra algo. La base por defecto es 10
   en el caso de que no se detecte ninguno de esos prefijos.

double ustrtod(const char *s, char **endp);
   Convierte en nmero de coma flotante tantos carcteres de s que parezcan
   un nmero en coma flotante, y hace que *endp apunte al primer carcter no
   usado, si endp no es un puntero nulo.

const char *ustrerror(int err);
   Esta funcin devuelve una cadena que describe el cdigo de error `err',
   que normalmente vendr de la variable `errno'. Devuelve un puntero a una
   cadena esttica que no debe ser modificada o liberada. Si hace llamadas
   posteriores a ustrerror, la cadena puede ser sobreescrita.

int usprintf(char *buf, const char *format, ...);
   Esta funcin escribe datos formateados en el buffer de salida. El
   carcter NULL es escrito para marcar el final de la cadena. Devuelve el
   nmero de carcteres que fueron escritos, sin inclur el carcter
   terminador nulo.

int uszprintf(char *buf, int size, const char *format, ...);
   Esta funcin escribe datos formateados en el buffer de salida, cuya
   longitud en bytes es especificada por size, y que est garantizado que
   acabar en carcter NULL. Devuelve el nmero de carcteres que se
   hubiesen escrito sin contar la truncacin eventual (como con usprintf), y
   sin inclur el carcter terminador NULL.

int uvsprintf(char *buf, const char *format, va_list args);
   Esto es como usprintf, pero usted pasa una lista variable de argumentos
   en vez de los propios argumentos.

int uvszprintf(char *buf, int size, const char *format, va_list args);
   Esto es como uszprintf(), pero usted pasa una lista variable de
   argumentos en vez de los propios argumentos.



=====================================================
============ 02 Rutinas de configuracin ============
=====================================================

Varias partes de Allegro, como las rutinas de sonido y la funcin
load_joystick_data, requieren cierta informacin de configuracin. Estos
datos son almacenados en ficheros de texto como una coleccin de lneas
"variable=valor", junto con comentarios que empiezan con el caracter '#' y
acaban al fina de la lnea. El fichero de configuracin puede estar dividido
en secciones que empiezan con una lnea "[nombreseccin]". Cada seccin
tiene un nombre nico, para prevenir conflictos con los nombres, pero la
variable que no est en una seccin determinada es considerada perteneciente
a todas simultneamente.

Por defecto los datos de configuracin se lee de un fichero llamado
allegro.cfg, que puede estar en el mismo directoria que el programa
ejecutable o en el directorio apuntado por la variable de entorno ALLEGRO.
En Unix tambin busca en ~/allegro.cfg, ~/.allegrorc, /etc/allegro.cfg, y
/etc/allegrorc, en ese orden; bajo BeOS slo comprueba los ds ltimos. Si
esto no te gusta puedes especificar cualquier nombre de fichero, o usar un
bloque binario de datos de configuracion proporcionado por tu programa (que,
por ejemplo, puede ser cargado desde un fichero de datos).

Puede almacenar cualquier informacin que quiera en el fichero de
configuracin, junto con las variables estndar usadas por Allegro (mire
abajo).

void set_config_file(const char *filename);
   Especifica el fichero de configuracin que ser usado por las siguientes
   rutinas de configuracin. Si no llama esta funcin, Allegro usar el
   fichero allegro.cfg, mirando primero en el directorio de su programa y
   luego en el directorio apuntado por la variable de entorno ALLEGRO.

   Todos los punteros devueltos por llamadas previas a get_config_string()
   y dems funciones similares son invalidados tras llamar a esta funcin!

void set_config_data(const char *data, int length);
   Especifica un bloque de datos que ser usados por las siguientes rutinas
   de configuracin, que previamente ha cargado del disco (ejemplo: como
   parte de un formato propio ms complicado, o desde un fichero de datos).
   Esta rutina hace una copia de la informacin, por lo que puede liberar
   los datos despus de llamarla.

void override_config_file(const char *filename);
   Especifica un fichero que contiene una configuracin de sobreescritura.
   Sus datos sern usados adems de los parmetros del fichero de
   configuracin principal, y si hay una misma variable en ambos ficheros,
   la del fichero de sobreescritura tendr preferencia. Esto puede ser usado
   por las aplicaciones del programador que deben tener ciertos valores de
   configuracin fijos, pero otros del fichero de configuracin principal
   pueden ser modificados por el usuario. Por ejemplo, podra especificar
   una frecuencia de muestreo de sonido y un fichero de instrumentos IBK
   especficos, pero el usuario podra usar un fichero sound.cfg o
   allegro.cfg para especificar los ajustes de su tarjeta de sonido
   (puertos, valores IRQ, etc).

void override_config_data(const char *data, int length);
   Versin de override_config_file() que usa un bloque de datos que ya ha
   sido cargado en memoria.

void push_config_state();
   Almacena el estado actual de configuracin (nombre de fichero, valores de
   las variables, etc) en una pila interna, permitindole seleccionar otro
   fichero de configuracin para despus recuperar la configuracin actual
   llamando pop_config_state(). Esta funcin est pensada para uso interno
   por otras funciones de la biblioteca, por ejemplo, cuando quiere
   especificar el fichero de configuracin de la funcin
   save_joystick_data(), almacena la configuracin actual antes de usar la
   del fichero especificado.

void pop_config_state();
   Recupera el estado previo de la configuracin almacenado por la funcin
   push_config_state() sobreescribiendo el cdigo del fichero de
   configuracin actual.

void flush_config_file();
   Escribe el contenido del fichero de configuracin actual al disco en caso
   de que haya cambiado desde que fue cargado o desde la ltima llamada a
   esta funcin.

void reload_config_texts(const char *new_language);
   Recarga las cadenas traducidas devueltas por get_config_text. Esto es
   til para cambiar a otro lenguaje en su programa en tiempo de ejecucin.
   Si quiere modificar manualmente la variable de configuracin [system]
   language, o ha cambiado de ficheros de comfiguracin, querr pasar NULL
   para recargar el lenguaje que est seleccionado actualmente. O puede
   pasar una cadena que contenga el cdigo de dos letras del lenguaje al que
   desea cambiar, y la funcin modificar la variable language. Tras la
   llamada a esta funcin, los punteros previamente devueltos por
   get_config_text sern invlidos.

void hook_config_section(const char *section,
       int (*intgetter)(const char *name, int def),
       const char *(*stringgetter)(const char *name, char *def),
       void (*stringsetter)(const char *name, const char *value));
   Toma control de la seccin especificada del fichero de configuracin,
   para que sus funciones de enganche sean usadas para manipularlo, en vez
   del acceso de disco normal. Si tanto las funciones getter como setter son
   NULL, un enganche presente ser desenganchado. Las funciones enganchadas
   tienen la mxima prioridad. Si una seccin est enganchada, la funcin de
   enganche siempre ser llamada, por lo que puede enganchar una seccin
   '#': incluso tengr prioridad sobre la funcin verride_config_file().

int config_is_hooked(const char *section);
   Devuelve TRUE si la seccin especificada est siendo enganchada.

char *get_config_string(const char *section,
                         const char *name, const char *def);
   Recupera la cadena de texto de la variable name del fichero de
   configuracin actual. Si la variable mencionada no es encontrada o su
   entrada est vaca, el valor def es devuelto. El nombre de seccin puede
   ser NULL para aceptar variables de cualquier parte del fichero, o puede
   ser usado para controlar en qu conjunto de parmetros (ejemplo: sonido o
   joystick) va a buscar la variable.

int get_config_int(const char *section, const char *name, int def);
   Lee un entero de la variable name del fichero de configuracin actual.
   Lea el comentario de la funcin get_config_string().

int get_config_hex(const char *section, const char *name, int def);
   Lee un entero de la variable name del fichero de configuracin actual, en
   formato hexadecimal. Lea el comentario de la funcin get_config_string().

float get_config_float(const char *section, const char *name, float def);
   Lee un nmero en coma flotante de la variable name del fichero de
   configuracin actual. Lea el comentario de la funcin
   get_config_string().

int get_config_id(const char *section, const char *name, int def);
   Lee una variable ID de 4 letras del fichero de configuracin actual. Lea
   el comentario de la funcin get_config_string();

char **get_config_argv(const char *section, const char *name, int *argc);
   Lee una lista de tokens (palabras separadas por espacios) del fichero de
   configuracin actual, devolviendo una lista de argumentos al estilo de
   argv, y ajustando argc al nmero de tokens (a diferencia de argc/argv,
   esta lista tiene como base el cero). Devuelve NULL y ajusta argc a cero
   si la variable no esta presente. La lista de tokens es almacenada en un
   buffer temporal que ser sobreescrito por la siguiente llamada a
   get_config_argv(), por lo que no espere que los datos persistan all.

char *get_config_text(const char *msg);
   Esta funcin es usada principalmente por cdigo interno de la biblioteca,
   pero tambin puede serle til a los programadores de aplicaciones. Usa el
   fichero language.dat o los ficheros XXtext.cfg (donde XX es el cdigo del
   lenguaje) para mirar una versin traducida del parmetro en el lenguage
   actualmente seleccionado, devolviendo una traduccin si sta existe o una
   copia del parmetro si no hay otra cosa disponible. Esto es bsicamente
   lo mismo que llamar get_config_string() con [language] como seccin, msg
   como nombre de variable, y msg como como valor por defecto, pero tiene
   cdigo especial aadido para manejar conversiones entre formatos Unicode.
   El parmetro msg siempre se pasa en ASCII, pero la cadena devuelta ser
   convertida al formato de texto actual, reservando memoria siempre que sea
   necesario, por lo que puede asumir que el puntero devuelto persistir,
   sin que tenga que reservar memoria manualmente para cada cadena.

void set_config_string(const char *section, const char *name,
                        const char *val);
   Escribe una cadena en la variable name del fichero de configuracin
   actual, sobreescribiendo cualquier valor previo, o borra la variable si
   val es NULL. El nombre de seccin puede ser NULL para escribir la
   variable en la raz del fichero, o puede ser usada para especificar la
   seccin en la que desea insertar la variable. El fichero alterado ser
   puesto en memoria cache, y no ser escrito en disco hasta que llame
   allegro_exit(). Tenga en cuenta que slo puede escribir en los ficheros
   de este modo, por lo que la funcin no tendr efecto si el fichero de
   configuracin actual fue especificado con set_config_data() en vez de con
   set_config_file().

   Como caso especial, las variables o nombres de seccin que comienzan con
   el carcter '#' son tratadas especialmente y no sern ledas o escritas
   en disco. Los paquetes adicionales pueden usar esto para almacenar
   informacin de version y otra informacin de estado en el mdulo de
   configuracin, desde el cual puede ser leda con la funcin
   get_config_string().

void set_config_int(const char *section, const char *name, int val);
   Escribe un entero en una variable en el fichero de configuracin actual.
   Lea el comentario de set_config_string().

void set_config_hex(const char *section, const char *name, int val);
   Escribe un entero en una variable en el fichero de configuracin actual,
   en formato hexadecimal. Lea el comentario de set_config_string().

void set_config_float(const char *section, const char *name, float val);
   Escribe un nmero en coma flotante en una variable en el fichero de
   configuracin actual. Lea el comentario de set_config_string().

void set_config_id(const char *section, const char *name, int val);
   Escribe una variable ID de 4 letras en el fichero de configuracin
   actual. Lea el comentario de la funcin set_config_string().

Allegro usa las siguientes variables estndar del fichero de configuracin:

[system]
   Seccin que contiene variables de propsito general, que son:

system = x
   Especifica que driver de sistema usar. Actualmente sto slo es til en
   Linux, para escoger entre los modos XWindows ("XWIN") o consola ("LNXC").

keyboard = x
   Especifica el mapa de teclado a usar. El parmetro es el nombre de un
   mapa de teclado producido por la utilidad keyconf, y puede ser un nombre
   de fichero normal o un nombre base como "us" o "uk". En este ltimo caso,
   Allegro buscar primero un fichero de configuracin independiente con ese
   nombre (ej: "uk.cfg") y despus un objeto con ese nombre en el fichero
   keyboard.dat (ej: "UK_CFG"). El fichero de configuracin o el fichero
   keyboard.dat pueden ser almacenados en el mismo directorio que su
   programa, o en una directorio apuntado por la variable de entorno
   ALLEGRO. Mire en el fichero keyboard.dat para ver los mapas de teclado
   disponibles.

language = x
   Especifica que fichero de lenguaje se usar para los mensajes de error y
   otros trozos de texto de sistema. El parmetro es el nombre de un fichero
   de traduccin, y puede ser o un path completo o un nombre "base" como "en"
   o "sp". Si es esto ltimo Allegro buscar primero un fichero de
   cofiguracin a parte, con un nombre con la forma "entext.cfg", y despus
   por un objeto con ese nombre en el fichero language.dat (ej: "
   ENTEXT_CFG"). El fichero de configuracin o el fichero language.dat pueden
   ser guardados en el mismo directorio que el programa o en el directorio
   apuntado por la variable de entorno ALLEGRO. Mire el fichero language.dat
   para saber que traducciones estn disponibles actualmente.

menu_opening_delay = x
   Ajusta el tiempo que tiene que pasar antes de que un men se abra
   automticamente. El tiempo se da en milisegundos (por defecto 300).
   Especificando -1 se desactivar la caracterstica de auto-apertura.

dga_mouse = x
   Slo X: desactive para evitar un fallo en algunos servidores X en
   modo DGA, concerniente al ratn. Por defecto est activado; active el
   parche ajustando la variable a "0".

dga_centre = x
   Slo X: indica al controlador DGA de Allegro que centre la pantalla si
   la resolucin actual es mayor que la del programa Allegro. Por defecto
   activada; desactvela ajustando la variable a "0".

dga_clear = x
   Slo X: indica al controlador DGA de Allegro limpiar la memoria de vdeo
   visible durante la inicializacin. Por defecto activada; desactvela
   ajustando la variable a "0".

[graphics]
   Seccin que contiene la configuracin grfica, usando las siguientes
   variables:

gfx_card = x
   Especifica el controlador grfico a usar cuando el programa haga una
   peticin GFX_AUTODETECT. Se pueden sugerir mltiples controladores
   posibles con lneas extra en la forma "gfx_card2 = x", "gfx_card3 = x",
   etc, o puede especificar diferentes controladores para cada modo y
   profundidad de color con variables tipo "gfx_card_24bpp = x",
   "gfx_card_640x480x16 = x", etc.

gfx_cardw = x
   Especifica qu driver grfico usar cuando el programa use
   GFX_AUTODETECT_WINDOWED. Esta variable funciona en lo dems exctamente
   igual que gfx_card. Si no existe, Allegro usar la variable gfx_card.

vbeaf_driver = x
   Slo DOS y Linux: especifica dnde buscar el controlador VBE/AF
   (vbeaf.drv). Si esta variable no est activada, Allegro buscar en el
   directorio del programa, y luego pasara a buscar en los sitios
   estndar (c:\ para DOS, /usr/local/lib, /usr/lib, /lib, y / para Linux, o
   el directorio especificado por la variable de entorno VBEAF_PATH).

framebuffer = x
   Slo para Linux: especifica el fichero de dispositivo que hay que usar con
   el controlador fbcon. Si esta variable no est activada, Allegro mirar en
   la variable de entorno FRAMEBUFFER. Por defecto se usar /dev/fb0.

[mouse]
   Seccin que contiene la configuracin del ratn, usando las siguientes
   variables:

mouse = x
   Tipos de driver para ratn. Los drivers disponibles para DOS son:
      MICK - driver en modo mickey (normalmente el mejor)
      I33  - Driver para atender a la interrupcin 0x33
      POLL - muestreo temporizado (para uso bajo NT)
   Los drivers para la consola de Linux son:
      MS   - Ratn srie de Microsoft
      IMS  - Ratn srie de Microsoft con extensin Intellimouse
      LPS2 - Ratn PS2
      LIPS - Ratn PS2 con extensin Intellimouse
      GPMD - repetidor de datos GPM (Protocolo Mouse Systems)

num_buttons = x
   Ajusta del nmero de botones de ratn vistos por Allegro. Normalmente no
   necesitar ajustar esta variable porque Allegro la autodetectar. Slo
   podr usarla para restringir el nmero de botones del ratn.

emulate_three = x
   Especifica si hay que emular un tercer botn de ratn detectando
   pulsaciones simultneas de los botones izquiedo y derecho (si o no). Por
   defecto activado (yes) si se dispone de un ratn de dos botones. En caso
   contrario, desactivado (no).

mouse_device = x
   Slo para Linux: especifica el nombre del archivo de dispositivo del
   ratn (ej: /dev/mouse).

mouse_accel_factor = x
   Slo Windows: especifica el factor de aceleracin del ratn. Por defecto
   es 1. Modifquelo a 0 para desactivar la aceleracin. Un 2 acelerar el
   ratn el doble que un 1.

[sound]
   Seccin que contiene la configuracin de sonido, usando las siguientes
   variables:

digi_card = x
   Elige el controlador para reproducir samples.

midi_card = x
   Elige el controlador para reproducir msica MIDI.

digi_input_card = x
   Determina el controlador de entrada de sonido digital.

midi_input_card = x
   Determina el controlador de entrada para datos MIDI.

digi_voices = x
   Especifica el nmero mnimo de voces que reservar el controlador de
   sonido digital. El nmero de voces posibles depende del controlador.

midi_voices = x
   Especifica el nmero mnimo de voces que reservar el controlador de
   msica MIDI. El nmero de voces posibles depende del controlador.

digi_volume = x
   Ajusta el volumen de reproduccin de sonidos, de 0 a 255.

midi_volume = x
   Ajusta el volumen de reproduccin de msica midi, de 0 a 255.

quality = x
   Controla la balanza calidad vs. rapidez del sonido del cdigo de mezcla
   de samples. Esto puede ser cualquiera de los siguientes valores:
      0 - mezcla rpida de datos 8 bit en buffers de 16 bits
      1 - mezcla verdadera de 16 bits (requiere una tarjeta de 16 bits
          estreo)
      2 - mezcla 16 bits interpolada

flip_pan = x
   Ajustando esto entre 0 y 1 invierte la panoramizacin izquierda/derecha
   de los samples, que puede ser necesaria porque algunas tarjetas SB
   (incluyendo la ma :-) crean la imagen estro al revs.

sound_freq = x
   DOS, Unix y BeOS: ajusta la frecuencia de los samples. Con el controlador
   de la SB, los valores posibles son 11906 (cualquier SB), 16129 (cualquier
   SB), 22727 (SB 2.0 y superiores), y 45454 (slo en SB 2.0 o SB16, no la SB
   Pro estreo). Con el controlador de la ESS Audiodrive, los valores
   posibles son 11363, 17046, 22729, o 44194. Con la Ensoniq Soundscape, los
   valores posibles son 11025, 16000, 22050, o 48000. Con Windows Sound
   System, los valores posibles son 11025, 22050, 44100, o 48000. No se
   preocupe si establece un valor inexistente por error: Allegro lo
   redondear automticamente a la frecuencia ms cercana soportada por su
   tarjeta de sonido.

sound_bits = x
   Unix y BeOS: establece el nmero de bits deseados (8 o 16).

sound_stereo = x
   Unix y BeOS: selecciona salida mono o estreo (0 o 1 respectivamente).

sound_port = x
   Slo DOS: establece el puerto de la tarjeta de sonido (normalmente 220).

sound_dma = x
   Slo DOS: establece el canal DMA de la tarjeta de sonido (normalmente 1).

sound_irq = x
   Slo DOS: establece el canal IRQ de la tarjeta de sonido (normalmente 7).

fm_port = x
   Determina el puerto del chip OPL (esto es normalmente 388).

mpu_port = x
   Determina el puerto de la interfaz MIDI MPU-401 (esto es normalmente 330).

mpu_irq = x
   Determina el IRQ del MPU-401 (esto es normalmente igual a sb_irq).

ibk_file = x
   Especifica el nombre de un fichero .IBK que ser usado para sustituir el
   conjunto estndar de instrumentos Adlib.

ibk_drum_file = x
   Especifica el nombre de un fichero .IBK que ser usado para sustituir el
   conjunto estndar de percusin Adlib.

oss_driver = x
   Slo Unix: establece el nombre del dispositivo OSS. Normalmente /dev/dsp o
   /dev/audio, pero podra ser un dispositivo particular (ej: /dev/dsp2).

oss_numfrags = x
oss_fragsize = x
   Slo Unix: establece el nmero de fragmentos (buffers) del controlador OSS
   y el tamao de cada buffer en samples. Los buffers son rellenados con
   datos durante la interrupcin donde el intervalo entre las siguientes
   interrupciones no es menor que 10 ms. Si el hardware puede reproducir toda
   la informacin de los buffers en menos de 10 ms, entonces se oirn clicks,
   cuando el hardware haya reproducido todos los datos y la biblioteca
   todava no ha preparado los nuevos datos. Por otra parte, si el hardware
   tarda mucho en reproducir los datos de los buffers, entonces habr
   restrasos entre las acciones que provocan los sonidos y los propios
   sonidos.

oss_midi_driver = x
   Slo Unix: establece el nombre del dispositivo MIDI OSS. Normalmente
   /dev/sequencer.

oss_mixer_driver = x
   Slo Unix: establece el nombre del mezclador OSS. Normalmente /dev/mixer.

esd_server = x
   Slo Unix: indica dnde encontrar el servidor ESD (Enlightened Sound
   Daemon).

alsa_card = x
alsa_pcmdevice = x
   Slo Unix: parmetros del sistema de sonido ALSA.

alsa_numfrags = x
   Slo Unix. nmero de fragmentos (buffers) del sistema de sonido ALSA.

alsa_fragsize = x
   Slo Unix: tamao de cada fragmento ALSA, en samples.

alsa_rawmidi_card = x
   Slo Unix: para el controlador MIDI de ALSA.

alsa_rawmidi_device = x
   Slo Unix: para el controlador MIDI de ALSA.

alsa_input_card = x
   Slo Unix: para el controlador MIDI de ALSA.

alsa_rawmidi_input_device = x
   Slo Unix: para el controlador MIDI de ALSA.

be_midi_quality = x
   Slo BeOS: calidad del sintetizador de instrumentos MIDI. 0 usa baja
   calidad de samples de 8-bit a 11kHz, 1 usa samples de 16-bit a 22kHz.

be_midi_freq = x
   Slo BeOS: frecuencia de mezclado de samples MIDI en Hz. Puede ser
   11025, 22050 o 44100.

be_midi_interpolation = x
   Slo BeOS: especifica el mtodo de interpolacin de samples MIDI. 0 para
   no usar interpolacin, es rpido pero de mala calidad; 1 hace una
   interpolacin rpida con buen rendimiento, pero es algo ms lento que lo
   anterior; 2 usa una interpolacin lineal entre samples, que es el mtodo
   ms lento pero con el cual se obtiene la mejor calidad.

be_midi_reverb = x
   Slo BeOS: intensidad de reverberacin, de 0 a 5. 0 la desactiva, un 5
   es el valor ms fuerte.

patches = x
   Especifica dnde encontrar el conjunto de samples para el controlador
   DIGMID. Esto puede ser un directorio al estilo Gravis conteniendo una
   coleccin de ficheros .pat y un ndice default.cfg, o un fichero de datos
   producido por la utilidad pat2dat. Si esta variable no es especificada,
   Allegro buscar un fichero default.cfg o patches.dat en el directorio del
   programa, en el directorio apuntado por la variable de entorno ALLEGRO, y
   en un directorio estndar GUS apuntado por la variable de entorno
   ULTRASND.

[midimap]
   Si est usando los controladores de salida MIDI SB o MPU-401 con un
   sintetizador externo que no es compatible General MIDI, puede usar la
   seccin midmap del fichero de configuracin para especificar una tabla de
   mapa para convertir los nmeros de los patches GM en sonidos apropiados
   de su sintetizador. Esto es una muestra real de indulgencia propia. Tengo
   un Yamaha TG500, que tiene algunos sonidos geniales pero no tiene
   conjunto de patches GM, y simplemente tena que hacerlo funcionar de
   alguna manera...

   Esta seccin consiste de una serie de lneas en la forma:

p<n> = bank0 bank1 prog pitch
   Con este comando, n es el nmero de programa GM a cambiar (1-128), bank0
   y bank1 son los dos bancos de mensajes de cambio a mandar a tu
   sintetizador (en controladores #0 y #32), prog es el mensaje de cambio de
   programa a tu sintetizador, y pitch es el nmero de semitonos a cambiar
   para todo lo que suene con ese sonido. Ajustando los nmeros de cambio de
   banco a -1 har que no sean mandados.

   Por ejemplo, la lnea:

      p36 = 0 34 9 12

   especifica que cuando el programa 36 GM (que es un bajo) sea
   seleccionado, Allegro mandar un mensaje de cambio de banco #0 con el
   parmetro 0, un mensaje de cambio de banco #32 con el parmetro 34, un
   cambio de programa con el parmetro 9, y entonces lo subir todo una
   octava.

[joystick]
   Seccin que contiene la configuracin del joystick, usando las siguientes
   variables:

joytype = x
   Especifica qu driver de joystick usar cuando el programa solicita usar
   JOY_TYPE_AUTODETECT.

joystick_device = x
   Slo BeOS: especifica el nombre del dispositivo joystick que ser usado.
   Por defecto se usa el primer dispositivo encontrado.

throttle_axis = x
   Slo Linux: establece en qu eje est localizado el mando de gases. Esta
   variable ser usada por cada joystick detectado. Si quiere especificar el
   eje de cada joystick individualmente, use variables con la forma
   throttle_axis_n, donde n sea el nmero del joystick.




=============================================
============ 03 Rutinas de ratn ============
=============================================

int install_mouse();
   Instala el controlador del ratn de Allegro. Debe hacer esto antes de
   usar cualquier otra funcin del ratn. Devuelve -1 si hubo error (ej. si
   el controlador int33 no est cargado), o el nmero de botones del ratn.

void remove_mouse();
   Quita el controlador de ratn. Normalmente no necesita llamar esta
   funcin, porque allegro_exit() lo har por usted.

int poll_mouse();
   Siempre que sea posible, Allegro leer la entrada del ratn asncronamente
   (ej: dentro de una interrupcin), pero en algunas plataformas esto puede
   no ser posible, en cuyo caso debe llamar a esta rutina en intervalos
   regulares para actualizar las variables de estado del ratn. Para ayudarle
   a comprobar que su cdigo de muestreo del ratn funciona incluso en una
   plataforma que no lo necesita, tras la primera llamada a esta rutina,
   Allegro entrar en modo muestreo, por lo que desde entonces en adelante
   deber llamar manualmente a esta funcin para obtener cualquier dato del
   ratn, sin importar si el controlador actual necesita ser muestreado o n.
   Devuelve cero con xito, o un nmero negativo si hubo un fallo (ej: no hay
   driver de ratn instalado).

int mouse_needs_poll();
   Devuelve TRUE si el controlador de ratn actual est siendo operado en
   modo muestreo.

extern volatile int mouse_x;
extern volatile int mouse_y;
extern volatile int mouse_b;
extern volatile int mouse_pos;
   Variables globales que contienen la posicin actual del ratn y el estado
   de los botones. Las posiciones mouse_x y mouse_y son enteros que van de
   cero a la esquina inferior derecha de la pantalla. La variable mouse_b es
   un campo de bits indicando el estado de cada botn: bit 0 es el botn
   izquierdo, bit 1 es del derecho, y bit 2 el botn central. Por ejemplo:

      if (mouse_b & 1)
         printf("El botn izquierdo est pulsado\n");

      if (!(mouse_b & 2))
         printf("El botn derecho no est pulsado\n");

   La variable pouse_pos contiene la coordenada X actual en la palabra alta
   y la coordenada Y en la palabra baja. Esto es til en bucles rpidos de
   lectura donde una interrupcin del ratn podra ocurrir mientras lee las
   dos variables por separado, ya que puede copiar este valor a una variable
   local con una instruccin, y entonces separarlo con tranquilidad.

extern BITMAP *mouse_sprite;
extern int mouse_x_focus;
exterm int mouse_y_focus;
   Variables globales que contienen el sprite actual del ratn y el punto
   del foco. Estas variables slo son de lectura, y slo se pueden
   modificar usando las funciones set_mouse_sprite() y
   set_mouse_sprite_focus().

void show_mouse(BITMAP *bmp);
   Le dice a Allegro que muestre el puntero del ratn en la pantalla. Esto
   slo funcionar si el mdulo de temporizacin est instalado. El puntero
   del ratn ser dibujado sobre el bitmap especificado, que ser
   normalmente 'screen' (lee ms abajo informacin sobre bitmaps). Para
   ocultar el puntero del ratn, llame show_mouse(NULL). Aviso: si dibuja
   algo en la pantalla mientras el puntero est visible, podra ocurrir una
   interrupcin de movimiento en medio de su operacin de dibujo. Si esto
   ocurre, el buffer del ratn y el cdigo de cambio de banco SVGA se
   confundirn, y dejarn 'rastros de ratn' por toda la pantalla. Para
   evitar esto, debe asegurarse que oculta el puntero del ratn siempre que
   vaya a dibujar la pantalla.

void scare_mouse();
   Funcin de ayuda para ocultar el puntero del ratn antes de una operacin
   de dibujado. Esto se deshar temporalmente del puntero del ratn, pero
   slo si es realmente necesario (ej. el ratn es visible, y est siendo
   visualizado en la pantalla fsica, y no se trata de un cursor por
   hardware). El estado previo del ratn es almacenado para las llamadas
   siguientes a unscare_mouse().

void scare_mouse_area(int x, int y, int w, int h);
   Como scare_mouse(), pero slo ocultar el cursor si ste se encuentra
   dentro del rectngulo especificado. Si no lo est, el cursor simplemente
   ser congelado hasta que llame a unscare_mouse(), para que no pueda
   interferir con su dibujado.

void unscare_mouse();
   Deshace el efecto de una llamada previa a scare_mouse(), recuperando el
   estado original del puntero.

extern int freeze_mouse_flag;
   Si esta variable est activa, el puntero del ratn no ser redibujado
   cuando mueva el ratn. Esto le puede evitar tener que ocultar el puntero
   cada vez que dibuje en la pantalla, siempre que no dibuje sobre la
   posicin actual del puntero.

void position_mouse(int x, int y);
   Mueve el ratn a la posicin de pantalla especificada. Puede llamar esta
   funcin incluso mientras el puntero est visible.

void position_mouse_z(int z);
   Establece la variable que contiene la posicin de la ruedecilla del ratn
   al valor indicado.

void set_mouse_range(int x1, int y1, int x2, int y2);
   Crea un rea de pantalla sobre la que el ratn se podr desplazar. Pase
   los parmetros de las esquinas del recuadro (coordenadas inclusivas). Si
   no llama esta funcin, el rea por defecto se activar a (0, 0,
   SCREEN_W-1, SCREEN_H-1).

void set_mouse_speed(int xspeed, int yspeed);
   Ajusta la velocidad del ratn. Valores grandes de xspeed e yspeed
   significan un movimiento ms lento: por defecto ambos son 2.

void set_mouse_sprite(BITMAP *sprite);
   No le gusta mi puntero de ratn? No problemo. Use esta funcin para usar
   uno propio alternativo. Si cambia el puntero y luego quiere volver a
   ver mi querida flecha otra vez, llame set_mouse_sprite(NULL).

   Como bonificacin, set_mouse_sprite(NULL) usa la paleta de colores
   actualmente seleccionada para elegir los colores de la flecha. Por lo que
   si el cursor se ve feo tras cambiar la paleta, llame a
   set_mouse_sprite(NULL).

void set_mouse_sprite_focus(int x, int y);
   El foco del ratn es la parte del puntero que representa la posicin
   actual del ratn, vamos, la posicin (mouse_x, mouse_y). Por defecto el
   foco est arriba a la izquierda de la flecha, pero si va a usar un
   puntero de ratn diferente, quizs deba alterar esto.

void get_mouse_mickeys(int *mickeyx, int *mickeyy);
   Mide cmo de lejos se ha movido el ratn desde la ltima llamada a esta
   funcin. El ratn seguir generando unidades de movimiento incluso cuando
   llegue al borde de la pantalla, por lo que esta forma de control puede
   ser til en juegos que requieran un rango de movimiento del ratn
   infinito.

extern void (*mouse_callback)(int flags);
   Llamado por el controlador de interrupciones siempre cuando el ratn se
   mueva o el valor de los botones cambie. Esta funcin debe ser bloqueada en
   memoria (locked), y debe ejecutarse muy rpido! Se le pasan los
   bits de evento que activaron la llamada, que son una mscara de bits
   que puede contener cualquiera de los siguientes valores 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, y
   MOUSE_FLAG_MOVE_Z.



=====================================================
============ 04 Rutinas de temporizacin ============
=====================================================

Allegro puede establecer varias funciones virtuales de temporizacin, todas
funcionando a diferentes velocidades.

Bajo DOS reprogramar el reloj contnuamente para asegurarse de que todas se
llaman en el momento adecuado. Dado que estas rutinas alteran el chip de
temporizacin de bajo nivel, estas rutinas no deben usarse con otras rutinas
de temporizacin del DOS, como la rutina uclock() del djgpp.

En otras plataformas estn implementados usando hilos, que corren de forma
paralela al hilo principal. Por lo tanto las rutinas de llamada instaladas
con temporizadores no bloquearn al hilo principal cuando sean llamadas, por
lo que podra necesitar dispositivos de sincronizacin apropiados (ej:
semforos, mutexes, etc) cuando acceda a datos compartidos por el hilo
principal y su rutina de temporizacin. (Por ahora Allegro no provee este
tipo de dispositivos de sincronizacin.)

int install_timer();
   Instala el controlador de temporizacin de Allegro. Debe hacer esto antes
   de instalar cualquier rutina de temporizacin propia, e incluso antes de
   visualizar el puntero del ratn, reproducir una animacin FLI, reproducir
   msica MIDI y usar cualquiera de las rutinas GUI. Devuelve cero con xito,
   o un nmero negativo si hubo problemas (pero puede decidir si quiere
   verificar el valor de retorno de esta funcin, dado que es muy poco
   probable que pueda fallar).

void remove_timer();
   Quita el controlador de temporizacin de Allegro (y, bajo DOS, devuelve el
   control del reloj al sistema operativo). Normalmente no hace falta llamar
   esta funcin, porque allegro_exit() lo har por usted.

int install_int(void (*proc)(), int speed);
   Instala un temporizador con el tiempo dado en nmero de milisegundos
   entre cada tick. Esto es lo mismo que hacer install_int_ex(proc,
   MSEC_TO_TIMER(speed)). Si llama esta rutina sin haber instalado primero
   el mdulo de temporizacin, install_timer() ser llamado automticamente.
   Si no hay ms espacio para aadir otro temporizador de usuario,
   install_int() devolver un nmero negativo, en otro caso devolver cero.

int install_int_ex(void (*proc)(), int speed);
   Aade una funcin a la lista de temporizadores del usuario, o si ya est
   instalada, ajusta su velocidad retroactivamente (es decir, hace como si
   el cambio de velocidad hubiese ocurrido precisamente en el ltimo tick).
   El valor se da en ticks de reloj, que son 1193181 por segundo. Puede
   convertir la velocidad a partir de otros formatos de tiempo con las
   siguientes macros:

      SECS_TO_TIMER(secs)  - pase el nmero de segundos entre cada tick
      MSEC_TO_TIMER(msec)  - pase el nmero de milisegundos entre cada tick
      BPS_TO_TIMER(bps)    - pase el nmero de ticks por segundo
      BPM_TO_TIMER(bpm)    - pase el nmero de ticks por minuto

   Si no queda espacio para un temporizador nuevo, install_int_ex()
   devolver un nmero negativo, o cero de otro modo. Slo puede haber 16
   temporizadores a la vez, y algunas partes de Allegro (cdigo GUI, rutinas
   para visualizar el puntero del ratn, rest(), el reproductor de ficheros
   FLI o MIDI) necesitan instalar sus propios temporizadores, por lo que
   debera evitar usar muchos a la vez.

   Su funcin ser llamada por el controlador de interrupciones de Allegro y
   no directamente por el procesador, por lo que puede ser una funcin normal
   en C, y no necesita ninguna funcin de envoltura. Sin embargo tenga en
   cuenta que ser llamada en contexto de interrupcin, lo que impone muchas
   restricciones sobre lo que puede hacer en ella. No debera usar grandes
   cantidades de pila, no puede hacer llamadas al sistema operativo o usar
   funciones de la biblioteca de C, o contener cdigo con operaciones en coma
   flotante, y debe ejecutarse rpidamente. No intente hacer cosas
   complicadas con su temporizador: como regla general debera ajustar un par
   de valores y actuar en consecuencia de stos dentro de su bucle de control
   principal.

   En un entorno DOS en modo protegido como djgpp, la memoria es virtualizada
   y puede ser paginada a disco. Debido a la no-reentrancia del DOS, si una
   paginacin al disco ocurre dentro de su funcin de temporizacin, el
   sistema morir de forma dolorosa, por lo que debe asegurarse de bloquear
   (lock) toda la memoria (de cdigo y datos) que sea modificada dentro de
   su rutina de temporizacin. Allegro bloquear todo lo que use, pero usted
   es responsable de bloquear su rutina de temporizacin. Las macros
   LOCK_VARIABLE(variable), END_OF_FUNCTION(nombre_de_funcion), y
   LOCK_FUNCTION(nombre_de_funcion) pueden ser usadas para simplificar esta
   tarea. Por ejemplo, si quiere que su temporizador incremente una variable
   de contador, debera escribir:

      volatile int contador;

      void mi_temporizador()
      {
         contador++;
      }

      END_OF_FUNCTION(mi_temporizador);

   y en su cdigo de inicio debera bloquear la memoria de esta manera:

      LOCK_VARIABLE(contador);
      LOCK_FUNCTION(mi_temporizador);

   Obviamente esto puede ser extrao si usa estructuras de datos
   complicadas y llama otras funciones desde su temporizador, por lo que
   debera crear sus temporizadores tan simples como pueda.

void remove_int(void (*proc)());
   Quita una funcin de la lista de temporizadores de usuario. Al finalizar
   su programa, allegro_exit() har esto automticamente.

int install_param_int(void (*proc)(void *), void *param, int speed);
   Como install_int(), pero a la rutina callback se le pasar una copia del
   puntero void especificado. Para desactivar este temporizador, use
   remove_param_int() en vez de remove_int().

int install_param_int_ex(void (*proc)(void *), void *param, int speed);
   Como install_int_ex(), pero a la rutina callback se le pasar una copia
   del puntero void especificado. Para desactivar este temporizador, use
   remove_param_int() en vez de remove_int().

void remove_param_int(void (*proc)(void *), void *param);
   Como remove_int(), pero se usa con las rutinas de temporizacin que tienen
   parmetros. Si hay ms de una copia de la misma rutina activa a la vez,
   elegir la rutina a desactivar comprobando el valor del parmetro (por lo
   que no puede tener ms de una copia de un mismo temporizador usando un
   parmetro idntico).

int timer_can_simulate_retrace()
   Comprueba si es posible sincronizar el mdulo de temporizacin con el
   retrazo del monitor, dependiendo del entorno y plataforma actual (por el
   momento esto slo es posible ejecutndo un el programa en modo DOS puro y
   en una resolucin VGA o modo-X). Devuelve distinto de cero si la
   simulacin es posible.

void timer_simulate_retrace(int enable);
   El controlador DOS de temporizacin puede ser usado para simular
   interrupciones de retrazo vertical. Una interrupcin de retrazo puede ser
   extremadamente til para implementar una animacion suave, pero
   desafortunadamente el hardware de la VGA no puede hacerlo. La Ega lo poda
   hacer, y algunas SVGA pueden pero no completamente, y de forma no
   suficientemente estandarizada para que sea til. Allegro soluciona esto
   programando el reloj para que genere una unterrupcin cuando crea que va
   a ocurrir, y leyendo la VGA dentro del controlador de interrupcin para
   asegurarse de que est sincronizado con el refresco del monitor. Esto
   funciona bastante bien en algunas situaciones, pero hay muchos problemas:

   - Nunca use el simulador de retrazo en modos SVGA. Funcionar con algunas
     tarjetas, pero no en otras, y tiene conflictos con la mayora de las
     implementaciones VESA. La simulacin de retrazo slo es fiable en el
     modo 13 de la VGA y en el modo-X.

   - La simulacin de retrazo no funciona bajo win95, porque win95 devuelve
     basura cuando intento leer el tiempo transcurrido del PIT. Si alguien
     sabe cmo solucionar esto, que por favor me mande un email!

   - La simulacin de retrazo conlleva mucha espera del controlador de
     temporizacin con las interrupciones desactivadas. Esto reducir la
     velocidad del sistema de forma significante, y podra causar esttica
     el reproducir sonidos con tarjetas SB 1.0 (ya que no soportan la
     auto-inicializacin DMA: las SB 2.0 y superiores funcionarn bien).

   Considerando todos estos problemas, se aconsejara no depender del
   simulador de retrazo vertical. Si est trabajando en modo-X, y no le
   importa que su programa funcione bajo win95, est bien, pero sera buena
   idea dejar al usuario la posibilidad de desactivarlo.

   La simulacin de retrazo debe ser activada antes de usar las funciones de
   triple buffer en resoluciones del modo-X. Esto puede ser til tambin
   como una simple deteccin de retrazo, ya que leer vsync() puede hacer que
   ignore algn retrazo de vez en cuando si justo una interrupcin de
   sonido o temporizacin ocurre a la vez. Cuando la simulacin de retrazo
   est activada, vsync() comprobar la variable retrace_count en vez de
   leer los registros de la VGA, para que no pierda ningn retrazo incluso
   si est siendo enmascarado por otras interrupciones.

int timer_is_using_retrace()
   Comprueba si el modulo de temporizacin est, en ese momento, sincronizado
   con el monitor o no. Devuelve distinto de cero si lo est.

extern volatile int retrace_count;
   Si el simulador de retrazo est instalado, esto es incrementado con cada
   retrazo vertical, de otro modo es incrementado 70 veces por segundo
   (ignorando los retrazos). Esto le permite controlar la velocidad de su
   programa sin tener que instalar funciones de temporizacin propias.

   La velocidad del retrazo depende del modo grfico. En el modo 13h y
   resoluciones en modo-X de 200/400 lneas hay 70 retrazos por segundo, y
   en modos-X de 240/480 lneas hay 60. Puede ser tan bajo como 50 (en modo
   376x282) o tan alto como 92 (en modo 400x300).

extern void (*retrace_proc)();
   Si el simulador de retrazo est instalado, esta funcin ser llamada
   durante cada retrazo, de otro modo es llamada 70 veces por segundo
   (ignorando los retrazos). Pngala a NULL para desactivar las llamadas.
   Esta funcin obedece las mismas reglas que los temporizadores normales (es
   decir: debe estar bloqueada (locked), y no puede llamar al DOS o funciones
   de libc) pero incluso ms: debe ejecutarse _muy_ rpido, o fastidiar la
   sincronizacin del reloj. El nico uso que veo para esta funcin es para
   hacer manipulaciones de paleta, ya que el triple buffering puede hacerse
   con la funcin request_scroll(), y la variable retrace_count puede ser
   usada para temporizar su cdigo. Si quiere alterar la paleta dentro de
   retrace_proc, debe usar la funcin inline _set_color() en vez de la
   corriente set_color() o set_palette(), y no debera intentar alterar ms
   de dos o tres colores de la paleta en un mismo retrazo.

void rest(long time);
   Una vez que Allegro reprograma el reloj, la funcin estndar delay() no
   funcionar, por lo que tendr que usar sta. El tiempo time se pasa en
   milisegundos.

void rest_callback(long time, void (*callback)())
   Como rest(), pero llama continuamente la funcin especfica mientras est
   esperando que pase el tiempo requerido.



===============================================
============ 05 Rutinas de teclado ============
===============================================

El controlador de teclado de Allegro proporciona entrada con bffer y un
conjunto de variables que guardan el estado actual de cada tecla. Fjese que
no es posible detectar correctamente todas y cada una de las combinaciones de
teclas, debido al diseo del teclado del PC. Combinaciones de dos o tres
teclas funcionarn bien, pero si presiona ms, probablemente las extras
sern ignoradas (exactamente qu combinaciones son posibles parecen variar
de un teclado a otro).

int install_keyboard();
   Instala el controlador de interrupciones de teclado de Allegro. Debe
   llamarla antes de usar cualquier otra funcin de teclado. Una vez
   instalado el controlador no podr usar las llamadas a sistema o las
   funciones de librera de C para acceder al teclado. Devuelve cero con
   xito, o un nmero negativo si hubo problemas (pero puede decidir si
   quiere verificar el valor de retorno dado que es muy poco probable que
   esta funcin falle). Tenga en cuenta que en algunas plataformas el teclado
   no funcionar a no ser que haya activado un modo grfico, incluso si esta
   funcin devuelve cero antes de haber llamado a set_gfx_mode.
   
void remove_keyboard();
   Desintala el controlador de teclado, devolviendo el control al sistema
   operativo. Normalmente no necesita llamar a esta funcin, porque
   allegro_exit() lo har por usted.

void install_keyboard_hooks(int (*keypressed)(), int (*readkey)());
   Slo debera usar esta funcion si *no* va a usar el resto del controlador
   de teclado. Debe ser llamada en vez de install_keyboar(), y le deja
   proporcionar rutinas de atencin para detectar y leer pulsaciones de
   teclado, que sern usadas por las funciones principales keypressed() y
   readkey(). Esto puede ser til si quiere usar el cdigo GUI de Allegro con
   un controlador de teclado propio, ya que permite al GUI acceder a la
   entrada de teclado desde su cdigo, saltndose el sistema de entrada
   normal de Allegro.

int poll_keyboard();
   Siempre que sea posible Allegro intentar leer del teclado asncronamente
   (por ejemplo deste un controlador de interrupcin), pero en algunas
   plataformas puede que no sea posible, en cuyo caso deber llamar a esta
   rutina a intervalos regulares para actualizar las variables de estado del
   teclado. Para ayudarle a comprobar su cdigo que muestrea el teclado
   incluso si est programando en una plataforma que no lo necesita, despus
   de la primera llamada Allegro cambiar a modo encuesta, as, en adelante,
   tendr que llamar a esta rutina para obtener la entrada de teclado, sin
   importar si el driver actual necesita ser ledo o no. La funciones
   keypressed(), readkey() y ureadkey() llaman a poll_keyboard()
   automticamente, as que slo tendra que usar esta funcin cuando acceda
   al array key[] y a la variable key_shifts. Devuelve cero con xito, o un
   nmero negativo si hubo algn problema (ej: no hay driver de teclado
   instalado).

int keyboard_needs_poll();
   Devuelve TRUE si el controlador actual de teclado est trabajando en
   modo muestreo.

extern volatile char key[KEY_MAX];
   Array de enteros que indica el estado de cada tecla, ordenado por
   scancode. Siempre que sea posible se actualizarn estos valores de forma
   asncrona, pero si keyboard_needs_poll() devuelve TRUE, deber llamar
   manualmente a poll_keyboard() para actualizarlos con el estado actual. Los
   scancodes estn definidos en allegro/keyboard.h como una serie de
   constantes KEY_* (abajo tiene un listado). Por ejemplo, podra escribir:

      if (key[KEY_SPACE])
         printf("La barra espaciadora est siendo pulsada\n");


   Tenga en cuenta que se supone que el array representa qu teclas estn
   fsicamente apretadas y cuales n, por lo que semnticamente slo es
   de lectura.

   Estos son los scancodes del teclado:

      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
   
extern volatile int key_shifts;
   Mscara de bits que contienen el estado actual de shift/ctrl/alt, de las
   teclas especiales de Windows y los carcteres de escape de los acentos.
   Siempre que sea posible se actualizarn estos valores de forma asncrona,
   pero si keyboard_needs_poll() devuelve TRUE, deber llamar manualmente a
   poll_keyboard() para actualizarlos con el estado actual.
   Puede contener cualquiera de los bits:

      KB_SHIFT_FLAG
      KB_CTRL_FLAG
      KB_ALT_FLAG
      KB_LWIN_FLAG
      KB_RWIN_FLAG
      KB_MENU_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

int keypressed();
   Devuelve TRUE si hay teclas esperando en el buffer de entrada. Esto es
   equivalente a la funcin kbhit() de la biblioteca libc.

int readkey();
   Devuelve el siguiente caracter del bffer de teclado en formato ASCII. Si
   el bffer est vaco espera hasta que se apriete una tecla. El byte de
   menos peso del valor de retorno contiene el cdigo ASCII de la tecla, y el
   byte de mayor peso el scancode. El scancode sigue siendo el mismo a pesar
   del estado de las teclas shift, ctrl y alt, mientras que al cdigo ASCII
   s que le afecta la pulsacin de shift y ctrl de la manera normal (shift
   cambia a maysculas, ctrl+letra da la posicin de la tecla en el alfabeto,
   ej: ctrl+A = 1, ctrl+B = 2, etc). Apretando alt+key se devuelve slo el
   scancode, con el cdigo ASCII cero en el byte de menor peso. Por ejemplo:

      if ((readkey() & 0xff) == 'd')            // por cdigo ASCII
         printf("Has pulsado 'd'\n");

      if ((readkey() >> 8) == KEY_SPACE)    // por cdigo scancode
         printf("Has pulsado Espacio\n");

      if ((readkey() & 0xff) == 3)              // ctrl+letter
         printf("Has pulsado Control+C\n");

      if (readkey() == (KEY_X << 8))        // alt+letter
         printf("Has pulsado Alt+X\n");

   Esta funcin no puede devolver carcteres mayores que 255. Si necesita
   leer entradas Unicode use ureadkey() en vez de readkey()

int ureadkey(int *scancode);
   Devuelve el siguiente caracter del bffer de teclado en formato Unicode.
   Si el bffer est vaco se espera hasta que se presione una tecla. El
   valor de retorno contiene el valor Unicode de la tecla, y si no es NULL,
   en el argumento se iniciar con el scancode. Al contrario que
   readkey() esta funcin es capaz de devolver carcteres mayores que 255.

int scancode_to_ascii(int scancode);
   Convierte el scancode dado a un caracter ASCII para esa tecla, devolviendo
   el resultado de apretar esa tecla sin shift ni capslock, o cero si la
   tecla no es un caracter generable o no se puede ser traducido.

void simulate_keypress(int key);
   Introduce una tecla en el buffer del teclado, como si el usuario la
   hubiese pulsado. El parmetro est el mismo formato que el devuelto por
   readkey().

void simulate_ukeypress(int key, int scancode);
   Introduce una tecla en el bffer de teclado, como si el usuario la hubiese
   pulsado. El parmetro est en el mismo formato devuelto por ureadkey()

extern int (*keyboard_callback)(int key);
   Si se activa, esta funcin es ser llamada por el controlador del teclado
   en respuesta a cualquier tecla. Se le pasar una copia del valor que se
   va a aadir al buffer de entrada, y la funcin puede devolver este valor
   sin modificar, devolver cero para que la tecla sea ignorada, o devolver un
   valor modificado que cambiar lo que readkey() va a devolver despus. Esta
   rutina se ejecuta en contexto de interrupcin, por lo que debe estar
   bloqueada (locked) en memoria.

extern int (*keyboard_ucallback)(int key, int *scancode);
   Versin Unicode de keyboard_callback(). Si se activa, esta funcin es
   llamada por el controlador de teclado en respuesta a cualquier pulsacin
   de tecla. Se le pasa el valor del caracter y el scancode que sern
   aadidos al bffer de entrada, puede modificar el valor del scancode, y
   devuelve un cdigo de tecla nuevo o modificado. Si cambia el scancode a
   cero y devuelve un cero la tecla ser ignorada. Esta rutina se ejecuta en
   un contexto de interrupcin, por lo que debe ser bloqueada (locked) en
   memoria.

extern void (*keyboard_lowlevel_callback)(int scancode);
   Si se, activa esta funcin es llamada por el controlador de teclado en
   respuesta a cada evento de teclado, tanto cuando se pulsa como cuando se
   suelta.  Se le pasar un byte de scancode puro, con el bit de ms peso
   desactivado si la tecla ha sido pulsada o activado si ha sido soltada.
   Esta rutina se ejecuta en un contexto de interrupcin, as que
   debe estar bloqueada (locked) en memoria.

void set_leds(int leds);
   Modifica el estado de los indicadores LED del teclado. El parmetro es
   una mscara de bits conteniendo cualquiera de los valores
   KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, y KB_CAPSLOCK_FLAG, o -1 para
   recuperar el comportamiento normal.

void set_keyboard_rate(int delay, int repeat);
   Inicializa la frecuendia de repeticin del teclado. Los tiempos se dan en
   milisegundos. Pasar cero desactivar la repeticin de teclas.

void clear_keybuf();
   Limpia el bffer de teclado.

extern int three_finger_flag;
   El controlador de teclado de djgpp proporciona una secuencia de 'salida
   de emergencia' que puede usar para salir de su programa. Si est
   ejecutando bajo DOS ser la combinacin ctrl+alt+del. La mayora de SSOO
   multitarea capturarn esta combinacin antes de que llegue al controlador
   de Allegro, en cuyo caso puede usar la combinacin alternativa
   ctrl+alt+fin. Si quiere desactivar este comportamiento en su programa
   ajuste esta variable a FALSE.

extern int key_led_flag;
   Por defecto las teclas BloqMays, BloqNum y BloqDesp activan los LEDS
   del teclado cuando son presionadas. Si las quiere utilizar en su juego
   (Ej. BloqMays para disparar) este comportamiento no es deseable, por lo
   que puede poner a cero esta variable para evitar que los LEDS sean
   actualizados.



================================================
============ 06 Rutinas de Joystick ============
================================================

int install_joystick(int type);
   Inicializa el joystick y calibra el valor de la posicin central. El
   parmetro typo debera ser, normalmente, JOY_TYPE_AUTODETECT, o mirar la
   documentacin especfica de la plataforma para tener una lista de los
   drivers disponibles. Debe llamar a esta rutina antes de usar cualquier
   otra funcin del joystick, y se debera asegurar que el joystick est en
   la posicin central en ese momento. Devuelve cero si no ha habido
   problemas. Tan pronto como haya instalado el mdulo de joystick, ya ser
   capaz de leer el estado de los botones y la informacin digital(on/off) de
   la direccin, que puede ser suficiente para algunos juegos. Si quiere
   obtener una entrada totalmente analgica necesitar usar las funciones de
   calibrate_joystick() para medir el rango exacto de las entradas: lea ms
   abajo.

void remove_joystick();
   Quita el controlador de joystick. Normalmente no necesita llamar a esta
   rutina, porque allegro_exit() lo har por usted.

int poll_joystick();
   El joystick no funciona por interrupciones, as que necesitar llamar a
   esta funcin una y otra vez para actualizar los valores globales de
   posicin. Devuelve cero con xito o un nmero negativo si hubo problemas
   (normalmente porque no haba driver de joystick instalado).

extern int num_joysticks;
   Variables globales que indican el nmero de joysticks activos. Los
   controlador actuales soportan un mximo de cuatro dispositivos.

extern JOYSTICK_INFO joy[n];
   Array global de informacin de estado del joystick, que es actualizado
   por la funcin poll_joystick(). Slo el primer elemento num_joysticks
   tendr informacin til. La estructura JOYSTICK_INFO est definida as:

      typedef struct JOYSTICK_INFO
      {
         int flags;                       - estado de este joystick
         int num_sticks;                  - cuntos joysticks activos?
         int num_buttons;                 - cuntos botones?
         JOYSTICK_STICK_INFO stick[n];    - informacin de estado del stick
         JOYSTICK_BUTTON_INFO button[n];  - informacin de estado de los
                                            botones
      } JOYSTICK_INFO;

   El estado de los botones es almacenado en la estructura:

      typedef struct JOYSTICK_BUTTON_INFO
      {
         int b;                           - estado del botn on/off
         char *name;                      - descripcin de este botn
      } JOYSTICK_BUTTON_INFO;

   Puede ensear los nombres de los botones como parte de una pantalla de
   configuracin en la que el usuario elige qu funcin desempear cada
   botn en su juego, pero en situaciones simples puede asumir con
   seguridad que los dos primeros elementos del array button sern siempre
   los controles principales de disparo.

   Cada joystick proveer una o ms entradas stick, de varios tipos. Estas
   pueden ser controles digitales que tienen siempre un valor especfico
   (ej. un gamepad, el sombrero del Flightstick Pro o Wingman Extreme, o un
   joystick normal que todava no ha sido calibrado), o pueden ser entradas
   analgicas con un rango suave de movimiento. Las palancas pueden tener un
   nmero diferente de ejes, por ejemplo un controlador direccional normal
   tiene dos, pero el mando de gases del Flightstick Pro slo tiene un eje,
   y es posible que el sistema pueda ser expandido en el futuro para
   soportar controladores 3d. La entrada de la palanca est descrita por la
   estructura:

      typedef struct JOYSTICK_STICK_INFO
      {
         int flags;                       - variable de estado
         int num_axis;                    - cuntos ejes tenemos?
         JOYSTICK_AXIS_INFO axis[n];      - informacin de estado del eje
         char *name;                      - descripcin de este stick
      } JOYSTICK_STICK_INFO;

   Un solo joystick puede proveer diferentes entradas de joystick, pero
   puede asumir con seguridad que el primer elemento del array stick ser
   el controlador principal de direccin.

   La informacin sobre los ejes del mando est almacenada en la
   subestructura:

      typedef struct JOYSTICK_AXIS_INFO
      {
         int pos;                         - posicin analgica del eje
         int d1, d2;                      - posicin digital del eje
         char *name;                      - descripcin de este eje
      } JOYSTICK_AXIS_INFO;

   Esto le da tanto entrada digital en el campo pos (que va de -128 a 128 o
   de 0 a 255, dependiendo del tipo de control) como valores digitales en los
   campos d1 y d2. Por ejemplo, cuando describe la posicin del eje X, el
   campo pos contendr la posicin horizontal de joystick, d1 ser activado
   si mueve a la izquierda, y d2 ser activado si mueve a la derecha. Allegro
   rellenar todos estos valores sin importar el tipo de joystick que est
   conectado, emulando el campo pos para joysticks digitales ponindolo a las
   posiciones mnima, central y mxima, y emulando los valores d1 y d2 con
   joysticks analgicos comparando la posicin actual con el punto central.

   La variable flags de la estructura joystick puede ser cualquier
   combinacin de los siguientes bits:

   JOYFLAG_DIGITAL
      Este control tiene entrada digital.

   JOYFLAG_ANALOGUE
      Este control tiene entrada analgica.

   JOYFLAG_CALIB_DIGITAL
      Este control ser capaz de proveer entrada digital una vez sea
      calibrado, pero ahora no lo hace.

   JOYFLAG_CALIB_ANALOGUE
      Este control ser capaz de proveer entrada analgica una vez sea
      calibrado, pero ahora no lo hace.

   JOYFLAG_CALIBRATE
      Indica que este control debe ser calibrado. Muchos dispositivos
      requieren mltiples pasos de calibracin, por lo que puede llamar la
      funcin calibrate_joystick() desde un bucle hasta que este bit
      desaparezca.

   JOYFLAG_SIGNED
      Indica que la posicin analgica est en formato con signo, que va de
      -128 a 128. Este es el caso de todos los controles direccionales 2d.

   JOYFLAG_UNSIGNED
      Indica que la posicin analgica est en formato sin signo, que va de
      0 a 255. Este es el caso de todos los mandos de gases 1d.

   Nota para la gente que escribe diferente: en caso que no quiera escribir
   "analogue", hay varios #defines en allegro/joystick.h que le permitirn
   escribir "analog" sin problemas.

char *calibrate_joystick_name(int n);
   Devuelve una descripcin textual del siguiente tipo de calibracin que
   ser hecha en el joystick especificado, o NULL si no hace falta ms
   calibracin.

int calibrate_joystick(int n);
   La mayora de los joysticks deben ser calibrados antes de poder ser
   usados de forma analgica. Esta funcin realiza la siguiente operacin en
   la serie de calibracin para el stick especificado, asumiendo que el
   joystick ha sido posicionado de la forma descrita por la llamada previa a
   calibrate_joystick_name(), devolviendo cero con xito. Por ejemplo, una
   rutina simple para calibrar los joysticks podra ser as:

      int i;

      for (i=0; i<;num_joysticks; i++) {
         while (joy[i].flags & JOYFLAG_CALIBRATE) {
            char *msg = calibrate_joystick_name(i);
            printf("%s, y pulsa una tecla\n", msg);
            readkey();
            if (calibrate_joystick(i) != 0) {
               printf("oops!\n");
               exit(1);
            }
         }
      }

int save_joystick_data(const char *filename);
   Despus de todos los dolores de cabeza al calibrar el joystick, no
   querr que el pobre usuario tenga que repetir el proceso cada vez que
   ejecuta su programa. Llame esta funcin para salvar los datos de
   calibracin del joystick en un fichero de configuracin especificado, que
   puede ser ledo por load_joystick_data(). Pase NULL como filename para
   escribir los datos en el fichero de configuracin seleccionado
   actualmente. Devuelve cero si no hubo problemas.

int load_joystick_data(const char *filename);
   Recupera los datos de calibrado previamente almacenados por
   save_joystick_data() o la utilidad setup. Esto ajusta todos los aspectos
   del cdigo de joystick: ni si quiera debe llamar initialise_joystick()
   si est usando esta funcin. Pasa NULL como filename para leer los datos
   del fichero de configuracin seleccionado actualmente. Devuelve cero si
   no hubo problemas: si falla, el estado del joystick queda indefinido y
   debe reiniciarlo desde el comienzo.

int initialise_joystick();
   Deprecado. Use install_joystick() en su lugar.



===========================================
============ 07 Modos grficos ============
===========================================

void set_color_depth(int depth);
   Especifica el formato grfico que ser usado en las siguientes llamadas a
   set_gfx_mode() y create_bitmap(). Las profundidades vlidas son 8 (por
   defecto), 15, 16, 24 y 32 bits.

void request_refresh_rate(int rate);
   Solicita que en la siguiente llamada a set_gfx_mode() se intente usar la
   velocidad de refresco especificada, si es posible. No todos los
   controladores son capaces de esto, e incluso cuando pueden, no todas las
   velocidades sern posibles en cualquier hardware, por lo que el resultado
   puede diferir de lo que haya pedido. Tras la llamada a set_gfx_mode(),
   puede usar get_refresh_rate() para saber qu velocidad de refresco fue
   seleccionada. Por el momento, slo el driver DOS VESA 3.0, X DGA 2.0 y
   algunos drivers de DirectX soportan esta funcin. La velocidad es
   especificada en Hz, ej: 60, 70. Para volver a la velocidad por defecto,
   pase el valor cero.

int get_refresh_rate(void);
   Devuelve la velocidad de refresco actual, si es conocida (no todos los
   controladores pueden devolver esta informacin). Devuelve cero si la
   velocidad de refresco actual es desconocida.

GFX_MODE_LIST *get_gfx_mode_list(int card);
   Intenta crear una lista de todos los modos de vdeo soportados por un
   driver grfico GFX determinado. Esta funcin devuelve un puntero a una
   lista de estructuras del tipo GFX_MODE_LIST que estan definidas como:

      typedef struct GFX_MODE_LIST {
         int num_modes;
         GFX_MODE *mode;
      } GFX_MODE_LIST;

   Si esta funcin devuelve NULL, significa que la llamada no tuvo xito. El
   puntero mode apunta a la verdadera lista de modos de vdeo.

      typedef struct GFX_MODE {
         int width, height, bpp;
      } GFX_MODE;

   Esta lista termina con un elemento { 0, 0, 0 }.

void destroy_gfx_mode_list(GFX_MODE_LIST *mode_list);
   Borra de la memoria la lista de modos creada por get_gfx_mode_list().

int set_gfx_mode(int card, int w, int h, int v_w, int v_h);
   Cambia a modo grfico. El parmetro card normalmente debera ser
   GFX_AUTODETECT, GFX_AUTODETECT_FULLSCREEN o GFX_AUTODETECT_WINDOWED, o
   puede mirar la documentacin especfica de su plataforma para tener una
   lista los drivers disponibles. Los parmetros w y h especifican que
   resolucin de pantalla quiere.

   Los parmetros v_w y v_h especifican el tamao mnimo de la pantalla
   virtual, en caso de que necesite una pantalla virtual grande para hacer
   scroll por hardware o intercambio de pginas. Debera ponerlos a cero si
   no le importa la pantalla virtual. Las pantallas virtuales crean mucha
   confusin, pero en realidad son muy simples. Aviso: ahora viene una
   explicacin condescendiente, por lo que quizs quiera saltarse el resto
   del prrafo :-) Imagnese la memoria de vdeo como una pieza rectangular
   de papel que es vista a travs de un pequeo agujero (su monitor) hecho
   sobre cartn. Ya que el papel es ms grande que el agujero, slo puede
   ver una parte de l cada vez, pero moviendo el cartn puede alterar qu
   porcin est visualizando. Puede dejar el agujero en una posicin e
   ignorar el resto de la memoria de vdeo no visible, pero puede conseguir
   una gran variedad de tiles efectos desplazando la ventana de
   visualizacin, o dibujando en una parte de la memoria de vdeo no
   visible, y entonces intercambiar pginas para visualizar la nueva
   pantalla.

   Por ejemplo, puede seleccionar el modo 640x480 en el cual el monitor
   acta como una ventana sobre la pantalla virtual de 1024x1024, y
   entonces mover la pantalla visible dentro del rea grande. Inicialmente,
   la parte visible est posicionada en la parte superior izquierda de la
   memoria de vdeo. Esta configuracin sera as:

      (0,0)------------(640,0)----(1024,0)
      |                  |           |
      | pantalla visible |           |
      |                  |           |
      (0,480)----------(640,480)     |
      |                              |
      | resto de la memoria de vdeo |
      |                              |
      (0,1024)--------------------(1024,1024)

   Qu es eso? Est viendo esto con una fuente proporcional? Jejeje.

   Cuando llama set_gfx_mode(), los parmetros v_w y v_h representan el
   tamao mnimo de la pantalla virtual que es aceptable para su programa.
   El rango de tamaos posibles es normalmente muy restringido, y es posible
   que Allegro acabe creando una pantalla virtual ms grande que la que
   solicit. En una SVGA con una mega de vram cuente con conseguir una
   pantalla virtual de 1024x1024 (256 colores) o 1024x512 (15 o 16 bpp), y
   con 512k de ram puede conseguir 1024x512 (256 colores). Otros tamaos
   pueden ser y no ser posibles: no asuma que vayan a funcionar. En modo-X
   la anchura virtual puede ser cualquier mltiplo de 8 mayor o igual a la
   anchura de la pantalla, y la altura virtual se ajustar de la misma forma
   (la VGA tiene 256k de vram, por lo que la altura virtual ser
   256*1024/virtual_width).

   Despus de seleccionar el modo grfico, los tamaos fsicos y virtuales de
   la pantalla pueden obtenerse mediante las macros SCREEN_W, SCREEN_H,
   VIRTUAL_W, y VIRTUAL_H.

   Si Allegro no es capaz de seleccionar un modo apropiado, set_gfx_mode()
   devuelve un modo negativo y almacena la descripcin del problema en
   allegro_error. De otro modo devuelve cero.

   Como caso especial, si usa el cdigo de driver mgico GFX_SAFE, Allegro
   garantizar que el modo siempre ser establecido correctamente. Intentar
   seleccionar la resolucin que pidi, y si falla, usar aquella resolucin
   que sea fiable en la plataforma actual (esto es modo VGA a 320x200 bajo
   DOS, una resolucin de 640x480 bajo Windows, la resolucin actual del
   framebuffer bajo Linux si est soportada, etc). Si no puede establecer
   ningn modo grfico de ninguna manera, devolver un valor negativo
   indicando que debera abortar inmediatamente su programa, posiblemente
   tras informar al usuario de este hecho mediante allegro_message. Este
   driver falso es til para situaciones en las que quiere establecer un modo
   grfico que funcione, y no puede perder el tiempo probando diferentes
   resoluciones y haciendo la comprobacin de errores. Tenga en cuenta, que
   tras una llamada con xito a set_gfx_mode con este driver, no puede hacer
   ninguna asuncin sobre el ancho o alto de la pantalla o su profundidad de
   color: su cdigo deber tratar con este pequeo detalle.

   Finalmente, GFX_TEXT es otro driver mgico que normalmente cierra
   cualquier modo grfico abierto anteriormente, impidiendo que pueda usar
   la variable global screen, y en aquellos entornos que tienen modos de
   texto, vuelve a ajustar aqul ms parecido al activo antes de Allegro
   (normalmente 80x25). Con este driver los parmetros de tamao de
   set_gfx_mode no significan nada en absoluto, as que puede dejarlos a cero
   o cualquier otro nmero que prefiera.

int set_display_switch_mode(int mode);
   Establece de qu forma el programa debe manejar el hecho de ser enviado a
   un segundo plano si el usuario cambia a otro programa. No todos los modos
   posibles sern soportados por cada driver grfico en cada plataforma:
   debe llamar a esta rutina tras iniciar el modo grfico y si pide un modo
   que no es posible, esta rutina devolver -1. Los modos disponibles son:

   SWITCH_NONE
      Desactiva el cambio de modo. Este modo est por defecto en sistemas
      monotarea como el DOS. Puede ser soportado en otras plataformas, pero
      debera usarlo con cuidado, porque sus usuarios no se impresionarn si
      quieren cambiar de programa, pero usted no les deja!

   SWITCH_PAUSE
      Pone en pausa el programa mientras est en segundo plano. La ejecucin
      se restablecer tan pronto como el usuario vuelva al programa. Este
      modo est por defecto en la mayora de los entornos multitarea a
      pantalla completa, por ejemplo la consola de Linux.

   SWITCH_AMNESIA
      Como SWITCH_PAUSE, pero este modo no se preocupa en recordar el
      contenido de la memoria de vdeo, por lo tanto de la pantalla, y
      los bitmaps de vdeo que haya creado se eliminarn despus de que el
      usuario cambie de programa y vuelva otra vez. Este no es un modo
      terriblemente til pero es el modo por defecto para los modos a
      pantalla completa bajo Windows porque DirectDraw es demasiado intil
      para implementar algo mejor.

   SWITCH_BACKGROUND
      El programa seguir ejecutndose en background, con la variable screen
      apuntando temporalmente a un buffer de memoria en los modos de vdeo a
      pantalla completa. Debe tener especial cuidado cuando use este modo,
      porque ocurrirn cosas malas si el bitmap  de pantalla cambia cuando su
      programa no lo espera (lea ms abajo).

   SWITCH_BACKAMNESIA
      Como SWITCH_BACKGROUND, pero este modo no se preocupa por acordarse
      del contenido de la memoria de vdeo (vea SWITCH_AMNESIA). De nuevo,
      es el nico modo soportado por los drivers a pantalla completa de
      Windows que permite que su programa siga ejecutndose en segundo
      plano.

   Acurdese de tener mucho cuidado cuando use rutinas grficas durante un
   contexto de cambio: siempre deber llamar acquire_screen() antes de
   comenzar a dibujar en la pantalla y no la libere hasta que no haya acabado
   completamente, porque el mecanismo de fijado automtico puede no ser
   suficientemente bueno que funcione mientras el programa se ejecuta en
   segundo plano o acaba de de pasar al primer plano.

int set_display_switch_callback(int dir, void (*cb)());
   Instala una funcin de notificacin para el cambio de modo que fue
   previamente seleccionado por set_display_switch_mode(). El parmetro
   direction puede ser SWITCH_IN o SWITCH_OUT, dependiendo de si quiere ser
   avisado cuando se deje su programa o cuando se vuelva a l. A veces puede
   instalar funciones para las dos direcciones, pero no todas las plataformas
   las soportan, as esta funcin puede devolver -1 si su peticin es
   imposible. Puede instalar diferentes funciones de cambio de modo al mismo
   tiempo.

void remove_display_switch_callback(void (*cb)());
   Elimina una funcin de notificacin que fue previamente instalada mediante
   set_display_switch_callback(). Todas las funciones sern eliminadas
   automticamente cuando llame a set_display_switch_mode().

int get_display_switch_mode();
   Devuelve el modo de cambio de pantalla, en el mismo formato que se pasa a
   set_display_switch_mode().

extern int gfx_capabilities;
   Campo de bits describiendo las capacidades del controlador grfico y el
   hardware de video actuales. Puede contener cualquiera de los siguientes
   bits:

   GFX_CAN_SCROLL:
      Indica que la funcin scroll_screen() puede ser usada con este
      controlador.

   GFX_CAN_TRIPLE_BUFFER:
      Indica que las funciones request_scroll() y poll_scroll() se pueden
      usar con este driver. Si este bit no est activado es posible que la
      funcin enable_triple_buffer() sea capaz de activarlo.

  GFX_HW_CURSOR:
      Indica que un puntero de ratn por hardware est siendo usado. Cuando
      este bit est activado, puede dibujar sin problemas en la pantalla sin
      tener que ocultar antes el puntero del ratn. Tenga en cuenta que no
      todo cursor grfico puede ser implementado via hardware: en particular,
      VBE/AF slo soporta imgenes de 2 colores y de hasta 32x32 pixels,
      donde el segundo color es un inverso exacto del primero. Esto significa
      que Allegro puede necesitar alternar entre cursores por hardware o
      software en cualquier punto durante la ejecucin de su programa, por lo
      que no debe asumir que este bit ser constante durante largos periodos
      de tiempo. Slo le dice si un cursor hardware est siendo usado ahora,
      y puede cambiar cuando oculte/ensee el puntero.

GFX_HW_HLINE:
      Indica que la versin opaca normal de la funcin hline() est
      implementada usando aceleracin por hardware. Esto incrementar el
      rendimiento, no slo de hline(), sino tambin de otras funciones que
      la usen internamente, por ejemplo circlefill(), triangle(), y
      floodfill().

   GFX_HW_HLINE_XOR:
      Indica que la versin XOR de la funcin hline(), y cualquier otra que
      la use, estan implementadas usando aceleracin por hardware.

   GFX_HW_HLINE_SOLID_PATTERN:
      Indica que los modos slidos y con patrones de la funcin hline(), y
      cualquier otra funcin que la use, estan implementadas usando
      aceleracin por hardware (lea nota abajo).

   GFX_HW_HLINE_COPY_PATTERN:
      Indica que el modo copia de patrn de la funcin hline(), y cualquier
      otra funcin que la use, estan implementadas usando aceleracin por
      hardware (lea nota abajo).

   GFX_HW_FILL:
      Indica que la versin opaca de las funciones rectfill(), clear_bitmap()
      y clear_to_color(), estn implementadas usando aceleracin por
      hardware.

   GFX_HW_FILL_XOR:
      Indica que la versin XOR de la funcin rectfill() est implementada
      usando aceleracin por hardware.

   GFX_HW_FILL_SOLID_PATTERN:
      Indica que los modos slidos y con patrones de la funcin rectfill()
      estn implementados usando aceleracin por hardware (lea nota abajo).

   GFX_HW_FILL_COPY_PATTERN:
      Indica que el modo copia de patrn de la funcin rectill() est
      implementado usando aceleracin por hardware (lea nota abajo).

   GFX_HW_LINE:
      Indica que la versin opaca de las funciones line() y vline() est
      implementada usando aceleracin por hardware.

   GFX_HW_LINE_XOR:
      Indica que la versin XOR de las funcines line() y vline() est
      implementada usando aceleracin por hardware.

   GFX_HW_TRIANGLE:
      Indica que la versin opaca de la funcin triangle() est implementada
      usando aceleracin por hardware.

   GFX_HW_TRIANGLE_XOR:
      Indica que la versin XOR de la funcin triangle() est implementada
      usando aceleracin por hardware.

   GFX_HW_GLYPH:
      Indica que la expansin de carcter monocromo (para dibujo de texto)
      est implementada usando aceleracin hardware.

   GFX_HW_VRAM_BLIT:
      Indica que hacer un blit desde una parte de la pantalla a otra est
      implementado usando aceleracin por hardware. Si este bit est
      activado, hacer blits dentro de la memoria de vdeo ser ciertamente
      el modo ms rpido para ensear una imagen, por lo que sera til
      almacenar parte de sus grficos ms usados en una posicin oculta de
      la memoria de vdeo.

   GFX_HW_VRAM_BLIT_MASKED:
      Indica que la rutina masked_blit() es capaz de hacer una copia de una
      parte de vdeo a otra usando aceleracin por hardware, y que
      draw_sprite() usar copia por hardware cuando un sub-bitmap de la
      pantalla o un bitmap de memoria de vdeo sea la imagen origen. Si este
      bit est activado, el copiar desde la memoria de vdeo ser casi
      seguramente el modo ms rpido para visualizar una imagen, por lo que
      podra ser rentable almacenar algunos de sus sprites ms usados en una
      porcin no visible de la memoria de vdeo.

      Aviso: si esta bit no est activado, masked_blit() y draw_sprite() no
      funcionarn correctamente cuando los use con la memoria de vdeo como
      bitmap origen! Slo puede usar estas funciones para copiar memoria de
      vdeo si estn soportadas por el hardware.

   GFX_HW_MEM_BLIT:
      Indica que hacer un blit desde un bitmap de memoria a la pantalla usa
      aceleracin por hardware.

   GFX_HW_MEM_BLIT_MASKED:
      Indica que masked_blit() y draw_sprite() usan aceleracin por hardware
      cuando la imagen fuente es un bitmap de memoria, y la imagen destino
      es la pantalla fsica.

   GFX_HW_SYS_TO_VRAM_BLIT:
      Indica que hacer un blit desde un bitmap de sistema a la pantalla est
      acelerado por hardware. Note que puede haber alguna aceleracin incluso
      si este bit no est activado, porque los bitmaps de sistema tambin se
      pueden beneficiar del blit de memoria normal a la pantalla. Este bit
      slo estar activado si los bitmaps de sistema una aceleracin mayor
      que la proporcionada por GFX_HW_MEM_BLIT.

   GFX_HW_SYS_TO_VRAM_BLIT_MASKED:
      Indica que las funciones masked_blit() y draw_sprite() estn siendo
      aceleradas por hardware cuando la imagen fuente es un bitmap de sistema
      y el destino es la pantalla fsica. Note que puede haber alguna
      aceleracin incluso si este bit no est activado, porque los bitmaps de
      sistema tambin se pueden beneficiar del blit de memoria normal a la
      pantalla. Este bit slo estar activado si los bitmaps de sistema
      una aceleracin mayor que la proporcionada por GFX_HW_MEM_BLIT_MASKED.

   Nota: incluso cuando la informacin diga que el dibujo con patrn est
   soportado usando aceleracin por hardware, no ser posible para cualquier
   tamao de patrn. El controlador VBE/AF slo soporta patrones de hasta
   8x8 pixels, y usar la versin original no acelerada por hardware de las
   rutinas de dibujo siempre que use patrones ms grandes.

   Nota2: estas caractersticas de aceleracin por hardware slo surtirn
   efecto cuando dibuje directamente sobre la pantalla fsica, o un
   sub-bitmap de sta. La aceleracin por hardware es til sobre todo con
   una configuracin de cambio de pginas o triple buffer, y probablemente no
   habr diferencia de rendimiento con el sistema "dibuja en un bitmap de
   memoria, entonces cpialo a la pantalla".

int enable_triple_buffer();
   Si el bit GFX_CAN_TRIPLE_BUFFER de la variable gfx_capabilities no est
   activado, puede intentar activarlo llamando esta funcin. En particular,
   si est trabajando en modo-X bajo DOS puro, esta rutina activar el
   simulador de retrazo temporizado, el cual entonces activar las funciones
   de triple buffering. Devuelve cero si el triple buffering est activado.

int scroll_screen(int x, int y);
   Intenta hacer un scroll de la pantalla para mostrar una parte diferente de
   la pantalla virtual (que inicialmente se posicionar en 0,0, que es la
   esquina superior izquierda). Devuelve cero si ha tenido xito: puede
   fallar si el controlador grfico no soporta scroll por hardware o la
   pantalla virtual no es lo suficientemente grande. Puede usar esta funcin
   para mover la pantalla por un espacio de pantalla virtual grande, o para
   hacer un intercambio de pginas entre dos reas de pantalla virtual que
   no estn solapadas. Tenga en cuenta que para dibujar fuera de la posicin
   original de la pantalla deber alterar el rea de recorte: mire abajo.

   El scroll en Modo-X es de fiar y funcionar en cualquier tarjeta.
   Desafortunadamente la mayora de las implementaciones VESA slo pueden
   hacer scroll horizontal en incrementos de cuatro pixels, as que hacer
   un scroll suave en modos SVGA es imposible. Es vergonzoso, pero no veo
   forma de solucionarlo. Un numero significativo de implementaciones VESA
   parecen tener muchos fallos cuando hay que hacer scroll en modos
   truecolor, por lo que recomiendo no usar esta rutina en modos truecolor a
   menos que est seguro de que Scitech Display Doctor est instalado.

   Allegro se ocupar de cualquier sincronizacin del retrazo vertical cuando
   hago un scroll de pantalla, as que no necesita llamar a vsync() antes.
   Esto significa que scroll_screen() tiene los mismos efectos de retraso que
   vsync().

int request_scroll(int x, int y);
   Esta funcin es usada para el triple buffering. Hace una peticin de
   scroll por hardware a la posicin especificada, pero vuelve inmediatamente
   en vez de esperar un retrazo. El scroll tendr lugar durante el siguiente
   retrazo vertical, pero puede seguir ejecutando su cdigo mientras y usar
   la rutina poll_scroll() para detectar cuando ha ocurrido el cambio por
   scroll (vea examples/ex3buf.c). El triple buffering slo es posible en
   cierto hardware: funcionar en cualquier resolucin de modo-X si el
   simulador de retrazo esta activo(pero no funciona bien bajo win95), y est
   suportado por los controladores VBE 3.0 y VBE/AF para un nmero limitado
   de tarjetas grficas de alto nivel. Puede mirar el bit
   GFX_CAN_TRIPLE_BUFFER del campo de bits gfx_capabilities para ver si
   funcionar con el controlador actual. Esta funcin devuelve cero si no
   hubo problemas.

int poll_scroll();
   Esta funcin es usada con triple buffering. Comprueba el estado de un
   scroll por hardware iniciado previamente por la rutina request_scroll(),
   devolviendo no-cero si todava est esperando a que ocurra, y cero si ya
   ha ocurrido.

int show_video_bitmap(BITMAP *bitmap);
   Solicita intercambiar la pgina de pantalla hardware para visualizar el
   objeto bitmap de vdeo especificado, que debe tener el mismo tamao que
   la pantalla fsica, y debe haber sido obtenido usando la funcin
   create_video_bitmap(). Devuelve cero si no hubo problemas. Esta funcin
   esperar un retrazo vertical si su tarjeta de vdeo lo requiere, por lo
   que no hace falta que llame vsync() manualmente.

int request_video_bitmap(BITMAP *bitmap);
   Esta funcin se usa con triple buffering. Solicita intercambiar la pgina
   de pantalla al objeto bitmap de vdeo especificado, pero retorna
   inmediatamente en vez de esperar el retrazo. El intercambio tendr lugar
   con el siguiente retrazo vertical, pero puede mientras puede seguir
   ejecutando su cdigo y usar la rutina poll_scroll() para detectar cundo
   ocurre el intercambio realmente. Triple buffering slo es posible en
   determinado hardware: mire los comentarios de request_scroll(). Devuelve
   cero si no hubo problemas.



===========================================
============ 08 Objetos bitmap ============
===========================================

Una vez haya seleccionado un modo grfico, puede dibujar cosas en la
pantalla por el bitmap 'screen'. Todas las rutinas de dibujo de Allegro
dibujan en estructuras BITMAP, que son reas de memoria que contienen
imgenes rectangulares, almacenadas en arrays de packs de bytes (un byte por
pixel en modos de 8 bits, sizeof(short) bytes por pixel en modos de 15 y 16
bits por pixel, 3 bytes por pixel en modos de 24 bits y sizeof(long) bytes
por pixel en modos de 32 bits). Puede crear y manipular bitmaps en la memoria
RAM, o puede dibujar en el bitmap especial 'screen' que representa la memoria
de vdeo de su tarjeta grfica.

Por ejemplo, para dibujar un pixel en la pantalla escribira:

   putpixel(screen, x, y, color);

O para implementar un sistema doble-buffer:

   BITMAP *bmp = create_bitmap(320, 200);    // crea un bitmap en la RAM
   clear_bitmap(bmp);                        // limpia el bitmap
   putpixel(bmp, x, y, color);               // dibuja sobre el bitmap
   blit(bmp, screen, 0, 0, 0, 0, 320, 200);  // lo copia a la pantalla

Mire abajo para saber cmo obtener acceso directo a la memoria de un bitmap.

Allegro soporta varios tipos diferentes de bitmaps:

   - El bitmap screen, que representa la memoria de vdeo de su hardware.
     Debe dibujar sobre l para que su imagen sea visible.

   - Bitmaps de memoria, que estn situados en la RAM del sistema y pueden
     ser usados para almacenar grficos o como espacios de dibujo temporales
     para sistemas doble buffer. Estos pueden ser obtenidos llamando
     create_bitmap(), load_pcx(), o al cargar un fichero de datos.

   - Sub-bitmaps. Estos comparten memoria de imagen con un bitmap padre (que
     puede ser la pantalla, un bitmap de memoria u otro sub-bitmap), por lo
     que dibujar en ellos tambin modificar al bitmap padre. Pueden tener
     cualquier tamao y estar localizados en cualquier parte del bitmap
     padre. Pueden tener sus propias reas de recorte, por lo que son tiles
     para dividir un bitmap en varias unidades ms pequeas, ej: partir una
     pantalla virtual grande en mltiples secciones (mire
     examples/exscroll.c).

   - Bitmaps de memoria de vdeo. Estos son creados con la funcin
     create_video_bitmap(), y normalmente son implementados como sub-bitmaps
     del objeto screen.

   - Bitmaps de sistema. Se crean mediante la funcin create_system_bitmap(),
     y estn a caballo entre los bitmaps de memoria y los de video. Viven
     en la memoria de sistema, as pues no estn limitado por la cantidad
     de ram de video de su tarjeta, pero se guardan en un formato especfico
     de la plataforma que puede activar una aceleracin hardware mejor de la
     que es posible con un bitmap de memoria normal (vea los bits
     GFX_HW_SYS_TO_VRAM_BLIT y GFX_HW_SYS_TO_VRAM_BLIT_MASKED en
     gfx_capabilities). A los bitmaps de sistema se debe acceder de la misma
     manera que a los bitmaps de video, usando las funciones de cambio de
     banco y las macro bmp_write*(). No todas las plataformas implementan
     este tipo de bitmap: si no estn disponibles create_system_bitmap()
     funcionar idnticamente igual que create_bitmap().

extern BITMAP *screen;
   Puntero global a un bitmap, de tamao VIRTUAL_W x VIRTUAL_H. Esto es
   creado por set_gfx_mode(), y representa la memoria de vdeo de su
   hardware. Slo una parte de este bitmap ser visible, de tamao SCREEN_W
   x SCREEN_H. Normalmente estar en la parte superior izquierda de la
   pantalla virtual, por lo que puede ignorar el resto de la pantalla
   virtual si no est interesado en scroll por hardware o intercambio de
   pginas. Para mover la ventana visible a otras partes del bitmap screen,
   llama scroll_screen(). Inicialmente el rea de recorte ser igual de
   grande que la pantalla fsica, por lo que si quiere dibujar en la
   pantalla virtual fuera de este rectngulo, deber ajustar el rea de
   recorte.

BITMAP *create_bitmap(int width, int height);
   Crea un bitmap de memoria con tamao width por height, y devuelve un
   puntero a l. El bitmap tendr el rea de recorte activada y ajustada al
   tamao total del bitmap. La memoria de la imagen no ser limpiada, por lo
   que probablemente tendr basura: debera limpiar el bitmap antes de
   usarlo. Esta rutina usa siempre el formato global de profundidad de color
   especificado al llamar set_color_depth().

BITMAP *create_bitmap_ex(int color_depth, int width, int height);
   Crea un bitmap de una profundidad de color especfica (8, 15, 16, 24 o 32
   bits por pixel).

BITMAP *create_sub_bitmap(BITMAP *parent, int x, y, width, height);
   Crea un sub-bitmap, es decir, un bitmap que comparte memoria con un
   bitmap ya existente, pero posiblemente con un tamao y rea de recorte
   diferentes. Cuando cree un sub-bitmap de la pantalla en modo-X, la
   posicin x debe ser un mltiplo de cuatro. La anchura y altura del
   sub-bitmap pueden extenderse fuera de los bordes del bitmap padre (sern
   recortados), pero el punto de origen debe estar en una regin del bitmap
   padre.

BITMAP *create_video_bitmap(int width, int height);
   Reserva un bitmap de memoria de vdeo del tamao especificado,
   devolviendo un puntero si funcion, o NULL si hubo algn error (ej: se
   has quedado sin memoria vram libre). Esto puede ser usado para reservar
   memoria de vdeo oculta para almacenar grficos preparados para
   operaciones aceleradas por hardware, o para crear mltiples pginas de
   vdeo que luego pueden ser visualizadas con show_video_bitmap(). Los
   bitmaps de memoria de vdeo son normalmente reservados usando el mismo
   espacio que el bitmap screen, ya que pueden sobreescribirlo: por lo tanto
   no es una buena idea usar screen al mismo tiempo que las superficies
   devueltas por esta funcin.

BITMAP *create_system_bitmap(int width, int height);
   Crea un bitmap en memoria de sistema del tamao especificado, devolviendo
   un puntero a l si no hubo problemas o NULL en caso contrario.

void destroy_bitmap(BITMAP *bitmap);
   Destruye un bitmap de memoria, sub-bitmap, bitmap de memoria de vdeo o un
   bitmap de sistema cuando ya no lo necesite.

void lock_bitmap(BITMAP *bitmap);
   Bajo DOS, fija toda la memoria usada por un bitmap. Normalmente no
   necesita llamar a esta funcin a no ser que est haciendo cosas realmente
   raras en su programa.

int bitmap_color_depth(BITMAP *bmp);
   Devuelve la profundidad de color del bitmap especificado (8, 15, 16, 24,
   o 32).

int bitmap_mask_color(BITMAP *bmp);
   Devuelve el color de mscara del bitmap especificado (el valor que es
   ignorado al dibujar sprites). En bitmaps de 256 colores es cero, y en
   bitmaps truecolor es rosa fucsia (rojo y azul al mximo, verde a cero).

int is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2);
   Devuelve TRUE si ambos bitmaps describen el mismo rea de dibujo, ej: sus
   punteros son iguales, uno es un sub-bitmap del otro, o ambos son
   sub-bitmaps de un padre comn.

int is_linear_bitmap(BITMAP *bmp);
   Devuelve TRUE si bmp es un bitmap lineal, es decir, es un bitmap de
   memoria, pantalla en modo 13h o SVGA. En bitmaps lineales puede usar las
   funciones _putpixel(), _getpixel(), bmp_write_line(), y bmp_read_line().

int is_planar_bitmap(BITMAP *bmp);
   Devuelve TRUE si bmp es un bitmap de pantalla plano (modo-X o Xtended).

int is_memory_bitmap(BITMAP *bmp);
   Devuelve TRUE si bmp es un bitmap de memoria, es decir, que fue creado
   llamando create_bitmap() o cargado de un fichero de datos o una imagen.
   Los bitmaps de memoria pueden ser accedidos con los punteros de lnea de
   la estructura bitmap, ej: bmp->line[y][x] = color.

int is_screen_bitmap(BITMAP *bmp);
   Devuelve TRUE si bmp es el bitmap screen, o un sub-bitmap de l.

int is_video_bitmap(BITMAP *bmp);
   Devuelve TRUE si bmp es el bitmap screen, o un bitmap de memoria de video,
   o un sub-bitmap de alguno de ellos.

int is_system_bitmap(BITMAP *bmp);
   Devuelve TRUE si bmp es un bitmap de sistema, o un sub-bitmap de uno.

int is_sub_bitmap(BITMAP *bmp);
   Devuelve TRUE si bmp es un sub-bitmap.

void acquire_bitmap(BITMAP *bmp);
   Bloquea el bitmap de memoria de vdeo especificado antes de dibujar en l.
   Esto no se aplica a los bitmaps de memoria, y slo afecta a algunas
   plataformas (Windows lo necesita, DOS no). Estas llamadas no son
   estrictamente necesarias, porque las rutinas de dibujo adquirirn el
   bitmap automticamente antes de acceder a l, pero bloquear una superficie
   de DirectDraw es muy lento, y obtendr mucho ms rendimiento si adquiere
   la pantalla slo una vez antes del inicio de la funcin de redibujado
   principal, y la suelta cuando el dibujado ha concluido completamente.
   Mltiples llamadas de adquisicin sern anidadas, y el bitmap slo ser
   liberado cuando el contador de bloqueo sea cero. Tenga cuidado porque los
   programas DirectX activan un bloqueo de exclusin mutua (mutex) siempre
   que una superficie es bloqueada, lo que impide que reciban cualquier
   mensaje de entrada, as que debe asegurarse de liberar todos sus bitmaps
   antes de usar alguna rutina de temporizacin, teclado o cualquier otra
   rutina no grfica!

void release_bitmap(BITMAP *bmp);
   Libera un bitmap que fue bloqueado previamente mediante una llamada a
   acquire_bitmap(). Si el bitmap fue bloqueado varias veces, deber
   liberarlo el mismo nmero de veces para que est verdaderamente
   desbloqueado.

void acquire_screen();
   Sinnimo de acquire_bitmap(screen);

void release_screen();
   Sinnimo de release_bitmap(screen);

void set_clip(BITMAP *bitmap, int x1, int y1, int x2, int y2);
   Cada bitmap tiene un rea de recorte asociada, que es el rea de pantalla
   sobre la que puede dibujar. Nada ser dibujado fuera de este espacio.
   Pase las dos esquinas opuestas del rea de recorte: stas son inclusivas,
   ej: set_clip(bitmap, 16, 16, 32, 32) le permitir dibujar en (16, 16) y
   (32, 32), pero no en (15, 15) o (33, 33). Si x1, y1, x2 e y2 son cero, el
   rea de recorte se desactivar, lo que puede acelerar algunas operaciones
   de dibujo (normalmente casi nada, aunque cualquier poco ayuda) pero harn
   que su programa muera horriblemente si intenta dibujar fuera de los
   bordes del bitmap.



==============================================
============ 09 Cargando imgenes ============
==============================================

Aviso: cuando use imgenes truecolor, siempre debe ajustar el modo grfico
antes de cargar cualquier dato. De otro modo el formato de pixel (RGB o BGR)
ser desconocido, y el fichero podra ser convertido errneamente.

BITMAP *load_bitmap(const char *filename, RGB *pal);
   Carga un bitmap desde un fichero, devolviendo un puntero al bitmap y
   almacenando los datos de la paleta en el lugar especificado, que debera
   ser un array de 256 estructuras RGB. Es responsable de destruir el bitmap
   cuando ya no lo necesite. Devuelve NULL si hubo errores. Por ahora esta
   funcin soporta ficheros BMP, LBM, PCX y TGA, determinando el tipo por la
   extensin del fichero. Si el fichero contiene una imagen truecolor, debe
   ajustar el modo de vdeo o llamar set_color_conversion() antes de
   cargarlo.

BITMAP *load_bmp(const char *filename, RGB *pal);
   Carga un fichero Windows u OS/2 de 256 colores o 24 bits truecolor.

BITMAP *load_lbm(const char *filename, RGB *pal);
   Carga un fichero IFF ILBM/PBM de 256 colores.

BITMAP *load_pcx(const char *filename, RGB *pal);
   Carga un fichero PCX de 256 colores o 24 bits truecolor.

BITMAP *load_tga(const char *filename, RGB *pal);
   Carga un fichero TGA de 256 colores, 15 bits hicolor, 24 bits truecolor o
   32 bits truecolor + canal alpha.

int save_bitmap(const char *filename, BITMAP *bmp, const RGB *pal);
   Escribe un bitmap en un fichero, usando la paleta especificada, que
   debera ser un array de 256 estructuras RGB. Devuelve distinto de cero si
   hubo errores. El formato de salida es determinado por la extensin del
   fichero: actualmente esta funcin soporta ficheros BMP, PCX o TGA. Una de
   las cosas con las que tener cuidado: si usa esto para volcar la pantalla
   en un fichero, puede acabar con una imagen ms grande de lo esperado, ya
   que Allegro suele crear pantallas virtuales ms grandes que la pantalla
   visible. Puede solucionar esto usando un sub-bitmap que especifica la
   parte de la pantalla que desea salvar, ejemplo:

      BITMAP *bmp;
      PALETTE pal;

      get_palette(pal);
      bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H);
      save_bitmap("pantalla.pcx", bmp, pal);
      destroy_bitmap(bmp);

int save_bmp(const char *filename, BITMAP *bmp, RGB *pal);
   Escribe un bitmap en un fichero BMP de 256 colores o 24 bits truecolor.

int save_pcx(const char *filename, BITMAP *bmp, RGB *pal);
   Escribe un bitmap en un fichero PCX de 256 colores o 24 bits truecolor.

int save_tga(const char *filename, BITMAP *bmp, RGB *pal);
   Escribe un bitmap en un fichero TGA de 256 colores, 15 bits hicolor, 24
   bits truecolor o 32 bits truecolor + canal alpha.

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));
   Informa a las funciones load_bitmap() y save_bitmap() de un nuevo tipo de
   fichero, dando rutinas para leer o escribir imgenes en este formato
   (cualquier funcin puede ser NULL).

void set_color_conversion(int mode);
   Especifica cmo convertir imgenes entre diferentes profundidades de color
   cuando se leen grficos desde archivos externos o ficheros de datos. El
   modo es
   una mscara de bits especificando qu tipos de conversin se permiten. Si
   se activa el bit apropiado, los datos sern convertidos al formato actual
   de pixel (seleccionado llamando a la funcin set_color_depth()), si n, se
   dejarn en el mismo formato que tenan en el fichero, debiendo entonces
   convertir manualmente el grfico antes de poder mostrarlo. El modo por
   defectos es la conversin total, as que todas las imgenes se cargarn
   en el modo apropiado para el modo de vdeo actual. Los bits vlidos son:

      COLORCONV_NONE            // desactiva las conversiones entre formatos
      COLORCONV_8_TO_15         // expande 8 bits a 15 bits
      COLORCONV_8_TO_16         // expande 8 bits a 16 bits
      COLORCONV_8_TO_24         // expande 8 bits a 24 bits
      COLORCONV_8_TO_32         // expande 8 bits a 32 bits
      COLORCONV_15_TO_8         // reduce 15 bits a 8 bits
      COLORCONV_15_TO_16        // expande 15 bits a 16 bits
      COLORCONV_15_TO_24        // expande 15 bits a 24 bits
      COLORCONV_15_TO_32        // expande 15 bits a 32 bits
      COLORCONV_16_TO_8         // reduce 16 bits a 8 bits
      COLORCONV_16_TO_15        // reduce 16 bits a 15 bits
      COLORCONV_16_TO_24        // expande 16 bits a 24 bits
      COLORCONV_16_TO_32        // expande 16 bits a 32 bits
      COLORCONV_24_TO_8         // reduce 24 bits a 8 bits
      COLORCONV_24_TO_15        // reduce 24 bits a 15 bits
      COLORCONV_24_TO_16        // reduce 24 bits a 16 bits
      COLORCONV_24_TO_32        // expande 24 bits a 32 bits
      COLORCONV_32_TO_8         // reduce 32 bits en RGB a 8 bits
      COLORCONV_32_TO_15        // reduce 32 bits en RGB a 15 bits
      COLORCONV_32_TO_16        // reduce 32 bits en RGB a 16 bits
      COLORCONV_32_TO_24        // reduce 32 bits en RGB a 24 bits
      COLORCONV_32A_TO_8        // reduce 32 bits en RGBA a 8 bits
      COLORCONV_32A_TO_15       // reduce 32 bits en RGBA a 15 bits
      COLORCONV_32A_TO_16       // reduce 32 bits en RGBA a 16 bits
      COLORCONV_32A_TO_24       // reduce 32 bits en RGBA a 24 bits
      COLORCONV_DITHER_PAL      // difumina al reducir a 8 bits
      COLORCONV_DITHER_HI       // difumina al reducir a hicolor
      COLORCONV_KEEP_TRANS      // mantiene la transparencia original

   Por conveniencia, las siguientes macros pueden usarse para seleccionar
   combinaciones comunes de los bits anteriores.

      COLORCONV_EXPAND_256          // expande 256 colores a hi/truecolor
      COLORCONV_REDUCE_TO_256       // reduce hi/truecolor a 256 colors
      COLORCONV_EXPAND_15_TO_16     // expande hicolor de 15 bit a 16 bits
      COLORCONV_REDUCE_16_TO_15     // reduce hicolor de 16 bits a 15 bits
      COLORCONV_EXPAND_HI_TO_TRUE   // expande 15/16 bits a 24/32 bits
      COLORCONV_REDUCE_TRUE_TO_HI   // reduce 24/32 bits a 15/16 bits
      COLORCONV_24_EQUALS_32        // convierte entre 24 and 32 bits
      COLORCONV_TOTAL               // todo al formato actual
      COLORCONV_PARTIAL             // convierte 15 <-> 16 y 24 <-> 32
      COLORCONV_MOST                // todas excepto hi/truecolor <-> 256

   Si activa el bit COLORCONV_DITHER, el difuminado se efectuar siempre
   que los grficos truecolor se conviertan a formato hicolor o modo con
   paleta, incluyendo la funcin blit(), y cualquier rutina de conversin
   automtica que se ejecute cuando lea grficos del disco. Esto puede
   producir resultados visuales ms atractivos, pero obviamente es mucho ms
   lento que una conversin directa.

   Si intenta usar bitmaps convertidos con funciones como masked_blit() o
   draw_sprite(), debera especificar el bit COLORCONV_KEEP_TRANS. Se
   asegurar de que las reas de mscara del bitmap antes y despus de la
   conversin se mantendrn iguales, convirtiendo los colores transparentes
   de un modo a otro y ajustando aquellos colores que tras la conversin
   podran ser reconvertidos en transparentes. Este bit afecta a cualquier
   llamada blit() entre formatos de pixel distintos y a cualquier conversin
   automtica.


 
==============================================
============ 10 Rutinas de paleta ============
==============================================

Todas las funciones de dibujo de Allegro usan parmetros en enteros para
representar colores. En las resoluciones truecolor estos nmeros codifican
el color directamente como una coleccin de bits rojos, verdes y azules,
pero en el modo normal de 256 colores, los valores son tratados como ndices
de la paleta actual, que es una tabla que contiene las intensidades de rojo,
verde y azul de cada uno de los 256 colores posibles.

La paleta se almacena con estructuras RGB, que contienen intensidades de
rojo, verde y azul en el formato hardware de la VGA, que van de 0 a 63, y
son definidas as:

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

Por ejemplo:

   RGB negro  = { 0,  0,  0  };
   RGB blanco = { 63, 63, 63 };
   RGB verde  = { 0,  63, 0  };
   RGB gris   = { 32, 32, 32 };

El tipo PALETTE es definido como un array de 256 estructuras RGB.

Puede notar que gran parte del cdigo de Allegro escribe 'palette' como
'pallete'. Esto es porque los ficheros de cabecera de mi viejo compilador
Mark Williams del Atari lo escriban con dos l's, y estoy acostumbrado a
eso. Allegro aceptar sin problemas ambas escrituras, debido a algunos
#defines en allegro/alcompat.h.

void vsync();
   Espera a que empiece un retrazo vertical. El retrazo ocurre cuando el
   rayo de electrones de su monitor ha llegado a la parte inferior de la
   pantalla y est volviendo arriba para hacer otro barrido. Durante este
   corto periodo de tiempo la tarjeta de vdeo no manda datos al monitor,
   por lo que puede hacer cosas que de otra forma no podra, como alterar
   la paleta sin causar parpadeo (nieve). Sin embargo Allegro esperar
   automticamente el retrazo vertical antes de alterar la paleta o hacer
   scroll por hardware, por lo que normalmente no debe preocuparse por esta
   funcin.

void set_color(int index, const RGB *p);
   Cambia la entrada de la paleta especificada al triplete RGB dado. A
   diferencia de otras funciones de paleta, esto no hace sincronizacin con
   el retrazo, por lo que debera llamar vsync() antes para evitar
   problemas de nieve.

void _set_color(int index, const RGB *p);
   Esta es una versin inline de set_color(), que puede usar en la funcin
   callback del simulador de retrazo vertical. Slo debera ser usada en
   VGA modo 13h y modo-X, porque algunos de las recientes SVGAs no son
   compatibles con la VGA (set_color() y set_palette() usarn llamadas VESA
   en estas tarjetas, pero _set_color() no sabr nada de eso).

void set_palette(const PALETTE p);
   Ajusta la paleta entera de 256 colores. Debe pasar un array de 256
   estructuras RGB. A diferencia de set_color(), no hace falta llamar
   vsync() antes de esta funcin.

void set_palette_range(const PALETTE p, int from, int to, int vsync);
   Ajusta las entradas de la paleta desde from hasta to (inclusivos: pase 0
   y 255 para ajustar la paleta entera). Si vsync est activado, espera un
   retrazo vertical, de otro modo cambia los colores inmediatamente.

void get_color(int index, RGB *p);
   Recupera la entrada de la paleta especificada.

void get_palette(PALETTE p);
   Recupera la paleta entera de 256 colores. Debe proveer un array de 256
   estructuras RGB para almacenar ah los colores.

void get_palette_range(PALETTE p, int from, int to);
   Recupera las entradas de la paleta desde from hasta to (inclusivos: pase
   0 y 255 para recuperar la paleta entera).

void fade_interpolate(const PALETTE source, const PALETTE dest,
        PALETTE output, int pos, int from, to);
   Calcula una paleta temporal en un sitio entre source y dest,
   devolvindola en el parmetro output. La posicin entre los dos extremos
   es especificada por el valor pos: 0 devuelve una copia exacta de source,
   64 devuelve dest, 32 devuelve una paleta a medio camino entre las dos,
   etc. Esta rutina slo afecta a los colores desde from hasta to
   (inclusivos: pase 0 y 255 para interpolar la paleta entera).

void fade_from_range(const PALETTE source, const PALETTE dest,
       int speed, int from, to);
   Funde gradualmente una parte de la paleta desde la paleta source hasta la
   paleta dest. La velocidad va de 1 (lento) a 64 (instantneo). Esta rutina
   slo afecta los colores desde from hasta to (inclusivos: pase 0 y 255
   para fundir la paleta entera).

void fade_in_range(const PALETTE p, int speed, int from, to);
   Funde gradualmente una parte de la paleta desde una pantalla negra hasta
   la paleta especificada. La velocidad va de 1 (lento) a 64 (instantneo).
   Esta rutina slo afecta los colores desde from hasta to (inclusivos: pase
   0 y 255 para fundir la paleta entera).

void fade_out_range(int speed, int from, to);
   Funde gradualmente una parte de la paleta desde la paleta actual hasta
   una pantalla negra. La velocidad va de 1 (lento) a 64 (instantneo). Esta
   rutina slo afecta los colores desde from hasta to (inclusivos: pase 0 y
   255 para fundir la paleta entera).

void fade_from(const PALETTE source, const PALETTE dest, int speed);
   Funde gradualmente desde la paleta source hasta la paleta dest. La
   velocidad va de 1 (lento) a 64 (instantneo).

void fade_in(const PALETTE p, int speed);
   Funde gradualmente desde una pantalla negra a la paleta especificada. La
   velocidad va de 1 (lento) a 64 (instantneo).

void fade_out(int speed);
   Funde gradualmente la paleta actual hasta una pantalla negra. La
   velocidad va de 1 (lento) a 64 (instantneo).

void select_palette(const PALLETE p);
   Rutina fea que puede usar en algunas situaciones peculiares cuando
   necesita convertir entre formatos de imagen con paleta a truecolor.
   Ajusta la tabla de la paleta interna de la misma forma que la funcin
   set_palette(), para que la conversin use la paleta especificada, pero
   sin afectar de ningn modo al hardware de visualizacin. La paleta
   antigua es almacenada en un buffer interno, y puede ser recuperada
   llamando unselect_palette().

void unselect_palette();
   Recupera la tabla de la paleta que estaba en uso antes de la ltima
   llamada a select_palette().

void generate_332_palette(PALETTE pal);
   Construye una paleta truecolor falsa, usando tres bits para el rojo y el
   verde y dos para el azul. La funcin load_bitmap() devuelve esto si el
   fichero no contiene ninguna paleta (ej. cuando lee un bitmap truecolor).

int generate_optimized_palette(BITMAP *bmp, PALETTE pal,
            const char rsvd[256]);
   Genera una paleta de 256 colores ptima para hacer una versin reducida,
   en cuanto a color, de la imagen truecolor especificada. El parmetro rsvd
   apunta a una tabla que indica qu colores se le permite modificar a la
   funcin: cero para colores libres que pueden ser asignados como el
   optimizador quiera, valores negativos para colores reservados que no
   pueden usarse, y valores positivos para entradas fijas de la paleta que
   no deben cambiarse, pero que se pueden usar en la optimizacin.

extern PALETTE default_palette;
   La paleta por defecto de la BIOS IBM. Se seleccionar automticamente
   cuando active un nuevo modo grfico.

extern PALETTE black_palette;
   Una paleta que contiene colores negros slidos, usada por las rutinas de
   fundidos.

extern PALETTE desktop_palette;
   La paleta usada por el escritorio de baja resolucin del Atari ST. No
   estoy seguro por qu esto sigue aqu, excepto porque los programas
   grabber y test la usan. Es probablemente el nico cdigo heredado del
   Atari que queda en Allegro, y sera una pena quitarlo :-)



========================================================
============ 11 Formatos de pixel truecolor ============
========================================================

En los modos de vdeo truecolor, los componentes rojo, verde y azul de cada
pixel son empaquetados directamente en el valor del color, en vez de ser un
ndice a una tabla de colores. En los modos de 15 bits hay 5 bits para cada
color, en modos de 16 bits hay 5 bits para rojo y azul y seis para verde, y
los modos de 24 y 32 bits usan ambos 8 bits para cada color (los pixels de
32 bits simplemente tienen un byte extra para alinear los datos). El mapa de
estos componentes puede variar entre ordenadores, pero generalmente ser RGB
o BGR. Ya que el mapa no es conocido hasta que seleccione el modo de vdeo
que vaya a usar, debe llamar set_gfx_mode() antes de usar cualquiera de las
siguientes rutinas!

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);
   Estas rutinas convierten los colores desde un formato independiente del
   hardware (rojo, verde y azul que van de 0 a 255) a varios formatos de
   pixel dependientes del hardware. Convertir entre formatos de 15, 16, 24 o
   32 bits slo requiere algunos desplazamientos de bits, por lo que es
   eficiente. Convertir hacia un color de 8 bits requiere buscar la paleta
   para encontrar el color ms parecido, algo que es muy lento a no ser que
   haya creado un mapa RGB (mire abajo).

int makeacol32(int r, int g, int b, int a);
   Convierte un color RGBA en un formato de pixel de pantalla de 32 bits, que
   incluye un valor alfa (de transparencia). No hay versiones de esta rutina
   para otras profundidades de color, porque slamente el formato de 32 bits
   tiene espacio suficiente para guardar un canal alfa til. Debera usar
   colores en formato RGBA slamente como entrada para draw_trans_sprite()
   o draw_trans_rle_sprite() despus de llamar a set_alpha_blender(), en vez
   de dibujarlos directamente en la pantalla.

int makecol(int r, int g, int b);
   Convierte colores desde un formato independiente del hardware (rojo,
   verde y azul que van de 0 a 255) al formato de pixel requerido por el
   modo de vdeo actual, llamando a las funciones previas makecol de 8, 15,
   16, 24, o 32 bits segn convenga.

int makecol_depth(int color_depth, int r, int g, int b);
   Convierte colores desde un formato independiente del hardware (rojo,
   verde y azul que van de 0 a 255) al formato de pixel requerido por la
   profundidad de color especificada.

int makeacol(int r, int g, int b, int a);
int makeacol_depth(int color_depth, int r, int g, int b, int a);
   Convierte colores RGBA en un formato de pixel dependiente de la pantalla.
   Si est en un modo inferior al de 32 bits, esto es lo mismo que llamar a
   makecol() o makecol_depth(), pero al usar esta rutine es posible crear
   valores de color de 32 bits que contienen un canal alpha verdadero de 8
   bits junto con los componentes rogo, verde y azul. Slo debera usar
   colores en formato RGBA como dato de entrada para draw_trans_sprite(), o
   draw_trans_rle_sprite() tras haber llamado a set_alpha_blender(), en vez
   de dibujarlos directamente en la pantalla.

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);
   Dados dos valores y coordenadas de pixel, calcula una valor RGB
   difuminado de 15 o 16 bits. Esto puede producir mejores resultados al
   reducir imgenes de truecolor a hicolor. Aparte de llamar estas funciones
   dirctamente, el difuminado hicolor puede ser activado automticamente al
   cargar grficos llamando la funcin set_color_conversion(), por ejemplo
   set_color_conversion(COLORCONV_REDUCE_TRUE_TO_HI | COLORCONV_DITHER).

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);
   Dado un color en un formato dependiente del hardware, estas funciones
   extraen uno de los componentes rojo, verde o azul (de 0 a 255).

int geta32(int c);
   Dado un color en un formato de pxel en 32 bits, esta funcin extrae el
   componente alfa (de 0 a 255).

int getr(int c);
int getg(int c);
int getb(int c);
int geta(int c);
   Dado un color en el formato usado por el modo de vdeo actual, estas
   funciones extraen uno de los componentes rojo, verde, azul o alfa (de 0 a
   255), llamando a las funciones previas get de 8, 15, 16, 24 o 32 bits
   segn convenga. La parte alfa slo tiene sentido para pxels de 32 bits.

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);
   Dado un color en el formato usado por la profundidad de color
   especificada, estas funciones extraen un componente rojo, verde, azul o
   alfa (de 0 a 255). La parte alfa slo tiene sentido para pxels de 32
   bits.

extern int palette_color[256];
   Tabla de mapa de la paleta que convierte un color (0-255) en el formato
   de pixel que est siendo usado por el modo de vdeo. En un modo de 256
   colores esto simplemente apunta al ndice del array. En modos truecolor
   mira el valor especificado en la paleta actual, y lo convierte a ese
   valor RGB en el formato de pixel empaquetado apropiado.

#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)
   Constantes que representan los colores usados para enmascarar los pixels
   transparentes de los sprites para cada profundidad de color. En
   resoluciones de 256 colores es cero, y en modos truecolor es rosa fucsia
   (rojo y azul al mximo, verde a cero).



=================================================
============ 12 Primitivas de dibujo ============
=================================================

Excepto _putpixel(), todas estas rutinas son afectadas por el modo actual de
dibujo y el rea de recorte del bitmap destino.

void putpixel(BITMAP *bmp, int x, int y, int color);
   Escribe un pixel en la posicin especificada del bitmap, usando el modo
   de dibujo actual y el rea de recorte del bitmap.

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);
   Como el putpixel() normal, pero mucho ms rpidas porque estn
   implementadas como funciones de ensamblador en lnea para profundidades
   de color especficas. No funcionarn en modos grficos de tipo Modo-X, no
   soportan reas de recorte (se bloquearn si intenta dibujar fuera del
   bitmap!), e ignoran el modo de dibujo.

int getpixel(BITMAP *bmp, int x, int y);
   Lee el pixel del punto x, y en el bitmap. Devuelve -1 si el punto est
   fuera del bitmap.

int _getpixel(BITMAP *bmp, int x, int y);
int _getpixel15(BITMAP *bmp, int x, int y);
int _getpixel16(BITMAP *bmp, int x, int y);
int _getpixel24(BITMAP *bmp, int x, int y);
int _getpixel32(BITMAP *bmp, int x, int y);
   Versiones ms rpidas de getpixel() para profundidades de color
   especficas. No funcionarn en modo-X y no soportan reas de recorte, as
   que debe estar seguro que el punto est dentro del bitmap.

void vline(BITMAP *bmp, int x, int y1, int y2, int color);
   Dibuja una lnea vertical en el bitmap, desde (x, y1) hasta (x, y2).

void hline(BITMAP *bmp, int x1, int y, int x2, int color);
   Dibuja una lnea horizontal en el bitmap, desde (x1, y) hasta (x2, y).

void do_line(BITMAP *bmp, int x1, y1, x2, y2, int d,
             void (*proc)(BITMAP *bmp, int x, int y, int d));
   Calcula todos los puntos de una lnea desde el punto (x1, y1) hasta (x2,
   y2), llamando la funcin proc para cada pixel. A sta funcin se le pasa
   una copia del parmetro bmp, la posicin x e y, y el parmetro d, por lo
   que puede llamar la funcin putpixel().
   
void line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
   Dibuja una lnea en el bitmap, desde (x1, y1) hasta (x2, y2).

void triangle(BITMAP *bmp, int x1, y1, x2, y2, x3, y3, int color);
   Dibuja un tringulo relleno entre los tres puntos.

void polygon(BITMAP *bmp, int vertices, int *points, int color);
   Dibuja un polgono relleno con un nmero arbitrario de vrtices. Pase el
   nmero de vrtices y un array que contenga series de puntos x e y (hasta
   un total del valor vertices*2).

void rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
   Dibuja los bordes de un rectngulo con los dos puntos dados como esquinas
   opuestas.

void rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
   Dibuja un rectngulo slido con los dos puntos dados como esquinas
   opuestas.

void do_circle(BITMAP *bmp, int x, int y, int radius, int d,
               void (*proc)(BITMAP *bmp, int x, int y, int d));
   Calcula todos los puntos de un crculo alrededor de (x, y) con el radio
   r, llamando a la funcin proc para cada pixel. A sta funcin se le pasa
   una copia del parmetro bmp, la posicin x e y, y el parmetro d, por lo
   que puede llamar la funcin putpixel().

void circle(BITMAP *bmp, int x, int y, int radius, int color);
   Dibuja un crculo con el centro y radio especificados.

void circlefill(BITMAP *bmp, int x, int y, int radius, int color);
   Dibuja un crculo relleno con el centro y radio especificados.

void do_ellipse(BITMAP *bmp, int x, int y, int rx, ry, int d,
                void (*proc)(BITMAP *bmp, int x, int y, int d));
   Calcula todos los puntos de una elipse alrededor de (x, y) con el radio
   rx y ry, llamando a la funcin proc por cada pixel. A sta funcin se le
   pasa una copia del parmetro bmp, la posicin x e y, y el parmetro d,
   por lo que puede llamar la funcin putpixel().

void ellipse(BITMAP *bmp, int x, int y, int rx, int ry, int color);
   Dibuja una elipse con el centro y radio especificados.

void ellipsefill(BITMAP *bmp, int cx, int cy, int rx, int ry, int color);
   Dibuja una elipse rellena con el centro y radio especificados.

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));
   Calcula todos los puntos en un arco circular alrededor del punto (x, y)
   con radio r, llamando a la funcin proc por cada uno de ellos. A sta se
   le pasar una copia del parmetro bmp, la posicin x e y, y una copia del
   parmetro d, por lo que puede usar putpixel(). El arco ser pintado en
   sentido antihorario empezando desde el ngulo a1 y terminando en a2.
   Estos valores deben ser especificados en fromato de punto fijo 16.16,
   siendo 256 un crculo total, 64 un ngulo recto, etc. Cero comienza a
   la derecha del punto central, y valores mayores rotan en direccin
   antihoraria desde ah.

void arc(BITMAP *bmp, int x, y, fixed ang1, ang2, int r, int color);
   Dibuja un arco circular con centro radio r y centro x, y, en direccin
   antihoraria empezando desde el ngulo a1 y terminando en a2. Estos
   valores deben ser especificados en fromato de punto fijo 16.16, siendo
   256 un crculo total, 64 un ngulo recto, etc. Cero comienza a la
   derecha del punto central, y valores mayores rotan en direccin
   antihoraria desde ah.

void calc_spline(int points[8], int npts, int *x, int *y);
   Calcula una serie de puntos npts a lo largo de una curva bezier,
   almacenndolos en los arrays x e y. La curva bezier es especificada por
   los cuatro puntos de control x/y del array points: points[0] y points[1]
   contienen las coordenadas del primer punto de control, points[2] y
   points[3] son el segundo punto de control, etc. Los puntos de control 0 y
   3 son los extremos de la curva, y los puntos 1 y 2 son las guas. La
   curva probablemente no pasar por los puntos 1 y 2, pero estos afectan a
   la forma de la curva entre los puntos 0 y 3 (las lneas p0-p1 y p2-p3 son
   tangentes de la curva bezier). La forma ms fcil de imaginrselo es
   pensar que la curva empieza en p0 en la direccin de p1, pero gira de tal
   forma que llega a p3 desde la direccin de p2. Adems de su rol de
   primitivas grficas, las curvas bezier pueden ser tiles para construir
   caminos alrededor de una serie de puntos de control, como en exspline.c.

void spline(BITMAP *bmp, int points[8], int color);
   Dibuja una curva bezier usando los cuatro puntos de control especificados
   en el array points.

void floodfill(BITMAP *bmp, int x, int y, int color);
   Rellena un rea cerrada, comenzando en el punto (x, y), con el color
   especificado.



============================================
============ 13 Blits y sprites ============
============================================

Todas estas rutinas son afectadas por el rea de recorte del bitmap destino.

void clear_bitmap(BITMAP *bitmap);
   Limpia el bitmap con el color 0.

void clear(BITMAP *bitmap);
   Un alias de clear_bitmap(), existe para mantener compatibilidad hacia
   atrs. Est implementado como una funcin esttica inline. El alias puede
   ser desactivado definiendo el smbolo de preprocesador
   ALLEGRO_NO_CLEAR_BITMAP_ALIAS antes de incluir los ficheros de cabecera
   de Allegro, por ejemplo:

      #define ALLEGRO_NO_CLEAR_BITMAP_ALIAS
      #include <allegro.h>

void clear_to_color(BITMAP *bitmap, int color);
   Limpia el bitmap con el color especificado.

void blit(BITMAP *source, BITMAP *dest, int source_x, int source_y,
          int dest_x, int dest_y, int width, int height);
   Copia un rea rectangular del bitmap origen en el bitmap destino. Los
   parmetros source_x y source_y son de la esquina superior izquierda del
   rea a copiar del bitmap origen, y dest_x y dest_y es la posicin
   correspondiente en el bitmap destino. Esta rutina respeta el rea de
   recorte del destino, y tambin habr recorte si intenta copiar reas que
   quedan fuera del bitmap origen.

   Puede hacer un blit entre cualquier parte de dos bitmaps, incluso si las
   dos reas se superponen (ejemplo: source y dest son el mismo bitmap, o
   uno es un sub-bitmap del otro). Debera tener en cuenta, sin embargo, que
   muchas tarjetas SVGA no tienen bancos de lectura/escritura separados, lo
   que significa que hacer un blit de una parte de la pantalla a otra
   requiere el uso de un bitmap de memoria temporal, y es por ello
   extremadamente lento. Como regla general debera evitar hacer blits de la
   pantalla sobre s misma en modos SVGA.

   Sin embargo, hacer un blit en modo-X de una parte de la pantalla a otro
   lado puede ser significantemente ms rpido que desde la memoria hacia la
   pantalla, siempre y cuando el origen y el destino estn correctamente
   alineados el uno con el otro. Hacer una copia entre reas de la pantalla
   que se superponen es lento, pero si las reas no se superponen, y si
   tienen la misma alineacin de planos (es decir: (source_x%4) ==
   (dest_x%4)), entonces se pueden usar los registros de la VGA para
   realizar una rpida transferencia de datos. Para tomar ventaja de esto,
   en modo-X normalmente se almacenan los grficos en una parte oculta de la
   memoria de vdeo (usando una pantalla virtual grande), y se hacen blits
   desde all a la parte visible de la pantalla.

   Si el bit GFX_HW_VRAM_BLIT est activado en la variable gfx_capabilities,
   el controlador actual soporta blits de una parte de la pantalla a otra
   usando aceleracin por hardware. Esto es extremadamente rpido, por lo
   que si este bit est activado, sera til almacenar parte de sus grficos
   ms frequentemente usados en una porcin oculta de la memoria de vdeo.

   Al contrario que la mayora de las rutinas grficas, blit() permite que
   los bitmaps de origen y destino sean de diferentes profundidades de
   color, por lo que se puede usar para convertir imgenes de un formato de
   pixel a otro.

void masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y,
                  int dest_x, int dest_y, int width, int height);
   Como blit(), pero salta los pixels transparentes (cero en modos de 256
   colores, y rosa fucsia para modos truecolor). La imagen origen debe ser un
   bitmap de memoria o un sub-bitmap, y las regiones de origen y destino no
   pueden superponerse.

   Si el bit GFX_HW_VRAM_BLIT_MASKED est activado en la variable
   gfx_capabilities, el controlador actual soporta blits de una parte de la
   pantalla a otra usando aceleracin por hardware. Esto es extremadamente
   rpido, por lo que si este bit est activado, sera til almacenar parte
   de sus grficos ms frequentemente usados en una porcin oculta de la
   memoria de vdeo.

   Atencin: si el bit de aceleracin por hardware no est activado,
   masked_blit() no funcionar correctamente cuando la imagen origen sea la
   memoria de vdeo, y el grfico a dibujar siempre tiene que ser un bitmap
   de memoria!

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);
   Como blit(), excepto que puede escalar imgenes de tal forma que las reas
   de origen y destino no tienen que tener el mismo tamao. Esta rutina no
   realiza tantas comprobaciones de seguridad como blit(): en particular debe
   tener cuidado de no copiar desde reas fuera del bitmap origen, y no puede
   hacer la copia entre reas que se superponen, y el bitmap origen y destino
   no pueden ser el mismo. Adems, el origen debe ser un bitmap de memoria o
   sub-bitmap, no la pantalla hardware.

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);
   Como stretch_blit(), pero se salta pixels transparentes, que estn
   marcados con un 0 en modos de 256 colores o magenta fara datos en
   truecolor (rojo y azul al mximo y el verde a  cero). Las regiones origen
   (source) y destino (destination) no deben solaparse.

void draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);
   Dibuja una copia del bitmap sprite en el bitmap destino en la posicin
   especificada. Eso es casi igual que blit(sprite, bmp, 0, 0, x, y,
   sprite->w, sprite->h), pero usa un modo de dibujado con mscara en el
   cual los pixels transparentes (cero en modos de 256 colores, rosa fucsia
   para modos truecolor) son ignorados, por lo que la imagen de fondo se
   podr ver por las partes enmascaradas del sprite. El sprite debe ser un
   bitmap de memoria, no la pantalla o un sub-bitmap. El destino puede ser
   cualquier bitmap.

   Si el bit GFX_HW_VRAM_BLIT_MASKED est activado en la variable
   gfx_capabilities, el controlador actual soporta blits de una parte de la
   pantalla a otra usando aceleracin por hardware. Esto es extremadamente
   rpido, por lo que si este bit est activado, sera til almacenar
   parte de sus grficos ms frequentemente usados en una porcin oculta de
   la memoria de vdeo.

   Atencin: si el bit de aceleracin por hardware no est activado,
   draw_sprite() no funcionar correctamente cuando la imagen origen sea la
   memoria de vdeo, y el grfico a dibujar siempre tiene que ser un bitmap
   de memoria!

   A pesar de no soportar generalmente grficos de diferentes profundidades
   de color, como caso especial puede usar esta funcin para dibujar
   imgenes origen de 256 colores en bitmaps destino truecolor, por lo que
   puede usar efectos de paleta en sprites especficos dentro de un
   programa truecolor.

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);
   Estas son como draw_sprite(), pero invierten la imagen sobre el eje
   vertical, horizontal o ambos. Esto produce imgenes espejo exactas, que
   no es lo mismo que rotar el sprite (y adems esto es ms rpido que la
   rutina de rotacin). El sprite debe ser un bitmap de memoria.

void draw_trans_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);
   Usa la tabla global color_map o las funciones de fundido truecolor para
   sobreimprimir un sprite encima de una imagen existente. Esto slo debe
   usarse si antes se ha creado la tabla de colores (para modos de 256
   colores) o las funciones de fundido (para modos truecolor). Ya que tiene
   que leer al igual que escribir en la memoria del bitmap, el dibujado
   translcido es muy lento si dibuja directamente en la memoria de vdeo,
   as que siempre que sea posibe debera usar un bitmap de memoria. El
   bitmap y el sprite deben, normalmente, tener la misma profundidad de
   color, pero como caso especial puede dibujar sprites en formato RGBA de
   32 bits en cualquier bitmap hicolor o truecolor, siempre y cuando llame
   primero a set_alpha_blender(), y puede dibujar imgenes con 8 bits de
   alfa en un destino en RGBA de 32 bits, mientras llame antes a
   set_write_alpha_blender().

void draw_lit_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int color);
   Entinta el sprite hacia el color o nivel de luz especificado, usando la
   tabla global color_map, y dibuja la imagen resultante en el bitmap
   destino. Esto slo se puede usar si antes ha creado una tabla de colores
   (para modos de 256 colores) o un mapa de fundido (para modos truecolor).

void draw_gouraud_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y,
                         int c1, int c2, int c3, int c4);
   Entinta el sprite al color o nivel de luz especificado, interpolando los
   cuatro colores de la esquina sobre la imagen. Esto slo se puede usar si
   antes ha creado una tabla de colores (para modos de 256 colores) o un
   mapa de fundido (para modos truecolor).

void draw_character(BITMAP *bmp, BITMAP *sprite, int x, int y, int color);
   Dibuja una copia del sprite en el bitmap destino en la posicin
   especificada, dibujando los pixels transparentes (cero en modos de 256
   colores, rosa fucsia en modos truecolor) con el modo de texto actual
   (ignorndolos si el modo de texto es -1, de otra forma los dibuja en el
   color de fondo del texto), y ajustando el resto de los pixels al color
   especificado. El sprite debe ser una imagen de 8 bits, incluso si el
   destino es un bitmap truecolor.

void rotate_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle);
   Dibuja el sprite en el bitmap destino. Ser colocado usando su esquina
   superior izquierda como la posicin especificada, y entonces ser rotado
   el ngulo especificado sobre su centro. El ngulo es un nmero de punto
   fijo 16.16 con el mismo formato usado por las funciones trigonomtricas
   de punto fijo, siendo 256 un crculo completo, 64 un ngulo recto, etc.
   Todas las funciones de rotacin pueden usar diferentes tipos de bitmaps
   de origen y destino, incluso bitmaps de pantalla o con una profundidad
   de color distinta.

void rotate_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle);
   Como rotate_sprite, pero tambin invierte la imgen verticalmente. Para
   invertir la imagen horizontalmente, use esta rutina pero aada
   itofix(128) al ngulo. Para invertir la imgen en ambos ejes, use
   rotate_sprite() y aada itofix(128) a su ngulo.

void rotate_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y,
                          fixed angle, fixed scale);
   Como rotate_sprite(), pero modifica el tamao de la imagen a la vez que
   la rota.

void rotate_scaled_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y,
                                 fixed angle, fixed scale)
   Dibuja el sprite, de forma similar a rotate_scaled_sprite(), excepto que
   primero invierte la imagen verticalmente.

void pivot_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y,
                  int cx, int cy, fixed angle);
   Como rotate_sprite(), pero toma el punto del sprite dado por (cx, cy) como
   (x, y) en el bitmap, y entonces lo rota sobre este punto.

void pivot_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y,
                         int cx, int cy, fixed angle);
   Como rotate_sprite_v_flip(), pero toma el punto del sprite dado por
   (cx, cy) como (x, y) en el bitmap, y entonces lo rota sobre este punto.

void pivot_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y,
                         int cx, int cy, fixed angle, fixed scale));
   Como rotate_scaled_sprite(), pero toma el punto del sprite dado por
   (cx, cy) como (x, y) en el bitmap, y entonces lo rota y escala sobre este
   punto.

void pivot_scaled_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y,
                                 fixed angle, fixed scale)
   Como rotate_scaled_sprite_v_flip(), pero toma el punto del sprite dado
   por (cx, cy) como (x, y) en el bitmap, y entonces lo rota y escala sobre
   este punto.

void stretch_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int w, int h);
   Dibuja un sprite en el bitmap en la posicin especificada, cambiando el
   tamao al ancho y alto especificado. La diferencia entre stretch_sprite()
   y stretch_blit() es que stretch_sprite() enmascara los pixels
   transparentes, que son cero en modos de 256 colores, y rosa fucsia en
   modos truecolor (rojo y azul al mximo, verde a cero).



========================================
============ 14 Sprites RLE ============
========================================

Ya que los bitmaps pueden ser usados de tantas maneras diferentes, la
estructura bitmap es bastante complicada y contiene muchos datos. En muchas
ocasiones, sin embargo, se encontrar almacenando imgenes que slo son
copiadas en la pantalla, en vez de pintar en ellas o usarlas como patrones
de relleno, etc. Si este es el caso, sera mejor que usase estas imgenes en
estructuras RLE_SPRITE o COMPILED_SPRITE en vez de bitmaps normales.

Los sprites RLE almacenan la imagen en un formato simple run-length, donde
los pixels cero repetidos son sustituidos por un contador de longitud, y las
series de pixels, que no son cero, son precedidos por un contador que da la
longitud del recorrido slido. Los sprites RLE son normalmente ms pequeos
que los bitmaps, tanto por la compresin run length como porque evitan la
mayora de sobrecarga de la estructura bitmap. Tambin son normalmente ms
rpidos que bitmaps normales, porque en vez de tener que comparar cada pixel
individual con cero para determinar si hay que dibujarlo, es posible
saltarse una serie de ceros con una simple suma, o copiar una serie larga de
pixels que no son cero con rpidas instrucciones de cadena.

Sin embargo no es oro todo lo que reluce, y hay una falta de flexibilidad
con los sprites RLE. No puede dibujar en ellos, y no puede invertirlos,
rotarlos o modificar su tamao. De hecho, lo nico que puede hacer con
ellos es copiarlos en un bitmap con la funcin draw_rle_sprite(), que es
equivalente a usar draw_sprite() con un bitmap normal. Puede convertir
bitmaps en sprites RLE en tiempo real, o puede crear estructuras de sprites
RLE en los ficheros de datos con el grabber, creando un nuevo objeto de tipo
'RLE sprite'.

RLE_SPRITE *get_rle_sprite(BITMAP *bitmap);
   Crea un sprite RLE basndose en el bitmap especificado (que debe ser un
   bitmap de memoria).

void destroy_rle_sprite(RLE_SPRITE *sprite);
   Destruye una estructura de sprite RLE previamente creada por
   get_rle_sprite().

void draw_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite,
       int x, int y);
   Dibuja un sprite RLE en el bitmap en la posicin especificada.

void draw_trans_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite,
             int x, int y);
   Versin translcida de draw_rle_sprite(). Vea la descripcin de
   draw_trans_sprite(). Slo debe ser usado despus de que haya creado
   la tabla de color (para modos de 256 colores) o funciones de fundido
   (para modos truecolor). El bitmap y el sprite deben, normalmente, tener
   la misma profundidad de color, pero como caso especial puede dibujar
   sprites en formato RGBA de 32 bits en cualquier bitmap hicolor o
   truecolor, siempre y cuando llame a set_alpha_blender() antes.

void draw_lit_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite,
           int x, y, color);
   Versin teida de draw_rle_sprite(). Lea la descripcin de
   draw_lit_sprite(). Esta slo debe usarse despus de que haya construdo
   la tabla de color (para modos de 256 colores) o funciones de fundido
   (para modos truecolor).



===============================================
============ 15 Sprites compilados ============
===============================================

Los sprites compilados se almacenan como instrucciones de cdigo mquina que
dibujan una imagen especfica sobre un bitmap, usando instrucciones mov con
valores de datos inmediatos. Esto es el mtodo ms rpido para dibujar una
imagen con mscara: en mi mquina, dibujar sprites compilados es unas cinco
veces ms rpido que usando draw_sprite() con bitmaps normales. Los sprites
compilados son grandes, por lo que si hay poca memoria, debera usar sprites
RLE, y lo que puede hacer con ellos esta incluso ms restringido que con
sprites RLE, porque no soportan reas de recorte. Si intenta dibujar uno
fuera de los bordes de un bitmap, corromper memoria y probablemente se
cargar el sistema. Puede convertir bitmaps en sprites compilados en tiempo
real, o puede crear complicadas estructuras de sprites compilados en los
ficheros de datos con el grabber creando un nuevo objeto de tipo 'Compiled
sprite' o 'Compiled x-sprite'.

COMPILED_SPRITE *get_compiled_sprite(BITMAP *bitmap, int planar);
   Crea un sprite compilado basndose en el bitmap especificado (que debe
   ser un bitmap de memoria). Los sprites compilados son dependientes de los
   dispositivos, por lo que debe especificar si compilarlo en un formato
   lineal o planar. Pase FALSE como segundo parmetro si va a dibujar en
   bitmaps de memoria o bitmaps de pantalla de modo 13h y SVGA, y pase TRUE
   si va a dibujarlos en bitmaps de pantalla modo-X o modo Xtended.

void destroy_compiled_sprite(COMPILED_SPRITE *sprite);
   Destruye una estructura de un sprite compilado previamente creado por
   get_compiled_sprite().

void draw_compiled_sprite(BITMAP *bmp, const COMPILED_SPRITE *sprite,
            int x, int y);
   Dibuja un sprite compilado en un bitmap en la posicin especificada. El
   sprite debe ser compilado segn el tipo correcto del bitmap (lineal o
   planar). Esta funcin no soporta reas de recorte.

   Ayuda: si el no poder recortar sprites compilados es un problema, un buen
   truco es crear una superficie de trabajo (bitmap de memoria, pantalla
   virtual en modo-X o lo que sea) un poco ms grande de lo que necesite, y
   usar el centro como su pantalla. De esta forma puede dibujar por afuera
   de los bordes sin ningn problema...



============================================
============ 16 Salida de texto ============
============================================

Allegro proporciona rutinas de salida de texto que funcionan tanto con
fuentes monocromo y color, que pueden contener cualquier nmero de rangos de
carcteres Unicode. El programa grabber puede crear fuentes desde conjuntos
de carcteres dibujados en un fichero bitmap (mire grabber.txt para ms
informacin), y tambin puede importar ficheros de fuentes en formato GRX o
BIOS. La estructura fuente contiene un nmero de engaches (hooks) que pueden
usarse para extenderla con su propio cdigo de dibujo: vea la definicin en
allegro/text.h para conocer los detalles.

extern FONT *font;
   Una fuente simple con un tamao fijo de 8x8 (del modo 13h de la BIOS). Si
   quiere alterar la fuente usada por las rutinas GUI, cambie esto para que
   apunte a una de sus fuentes. Esta funcin contiene los rangos estndar
   de carcteres ASCII (U+20 a U+7F), Latin-1 (U+A1 a U+FF) y Latin
   Extended-A (U+0100 a U+017F).

extern int allegro_404_char;
   Cuando Allegro no puede encontrar el grfico que necesita una fuente, en
   su lugar dibujar el carcter indicado por allegro_404_char. Por defecto
   ste es el smbolo del acento circumflejo, '^'.

int text_mode(int mode);
   Ajusta el modo en el que se dibujar el texto. Devuelve el valor previo.
   Si el modo es cero o positivo, la salida de texto ser opaca y el fondo
   de los carcteres sern ajustados al color #mode. Si mode es negativo, el
   texto ser dibujado de forma transparente (es decir, el fondo de los
   carcteres no ser alterado). Por defecto este modo es cero.

void textout(BITMAP *bmp, const FONT *f, const char *s,
    int x, y, int color);
   Escribe la cadena s en el bitmap en la posicin x, y, usando el modo de
   texto actual y el color de fondo y fuente especificado. Si el color es -1
   y se esta usando una fuente en color, se dibujar usando los colores de
   el bitmap de fuentes original (el que import en el programa grabber),
   lo que permite salida de texto multicolor.

void textout_centre(BITMAP *bmp, const FONT *f, const unsigned char *s,
           int x, y, color);
   Como textout(), pero interpreta la coordenada x como el centro y no como
   el margen izquierdo de la cadena.

void textout_right(BITMAP *bmp, const FONT *f, const char *s,
         int x, y, color);
   Como textout(), pero interpreta la coordenada x como la parte derecha de
   la cadena de texto.

void textout_justify(BITMAP *bmp, const FONT *f, const unsigned char *s,
                     int x1, int x2, int y, int diff, int color);
   Dibuja texto justificado dentro de la regin x1-x2. Si la cantidad de
   espacio reservado es mayor que el valor diff, se dar por vencido y
   dibujar un texto justificado por la izquierda.

void textprintf(BITMAP *bmp, const FONT *f, int x, y, color,
      const char *fmt, ...);
   Salida de texto formateada, usando un formato de cadena al estilo de
   printf().

void textprintf_centre(BITMAP *bmp, const FONT *f, int x, y, color,
        const char *fmt, ...);
   Como textprintf(), pero interpreta la coordenada x como el centro y no
   como el margen izquierdo de la cadena.

void textprintf_right(BITMAP *bmp, FONT *f, int x, y, color,
       const char *fmt, ...);
   Como textprintf(), pero interpreta la coordenada x como la parte derecha
   de la cadena.

void textprintf_justify(BITMAP *bmp, const FONT *f, int x1, int x2, int y,
                        int diff, int color, const char *fmt, ...);
   Como textout_justify, pero usando una cadena de formato printf.

int text_length(const FONT *f, const unsigned char *str);
   Devuelve la longitud (en pixels) de la cadena en la fuente especificada.

int text_height(const FONT *f)
   Devuelve la altura (en pixels) de la fuente especificada.

void destroy_font(FONT *f);
   Libera la memoria usada por una estructura de fuente.



=======================================================
============ 17 Renderizacin de polgonos ============
=======================================================

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[]);
   Dibuja polgonos 3d en el bitmap especificado, usando el modo de render
   especificado. A diferencia de la funcin polygon(), estas rutinas no
   soportan figuras cncavas o con intersecciones, y no pueden dibujar sobre
   bitmaps de pantalla en modo-X ( si quiere escribir cdigo en modo-X,
   dibuja en un bitmap de memoria y cpialo a la pantalla). El ancho y alto
   del bitmap de la textura debe ser un mltiplo de dos, pero puede ser
   diferente, ejemplo: una textura 64x16 est bien, pero una de 17x3 no. El
   parmetro que cuenta los vrtices (vc) debe ser seguido por un array que
   contiene el nmero apropiado de punteros a estructuras vertex:
   polygon3d() usa la estructura de punto fijo V3D, mientras que
   polygon3d_f() usa la estructura coma flotante V3D_f. Estas son definidas
   as:

      typedef struct V3D
      {
         fixed x, y, z;       - posicin
         fixed u, v;          - coordenadas de la textura
         int c;               - color
      } V3D;
   
      typedef struct V3D_f
      {
         float x, y, z;       - posicin
         float u, v;          - coordenadas de la textura
         int c;               - color
      } V3D_f;

   El cmo se almacenan los datos de los vrtices depende del modo de
   render:

   Los valores x e y especifican la posicin del vrtice en coordenadas de
   pantalla 2d.

   El valor z slo es necesario cuando use correccin de perspectiva en las
   texturas, y especifica la profundidad del punto usando coordenadas del
   mundo 3d.

   Las coordenadas u y v slo son necesarias cuando use texturas, y
   especifican la posicin del punto en el bitmap de la textura que se
   corresponde con el vrtice indicado. El plano de la textura es un plano
   infinito con el bitmap repetido sobre toda la superficie, y la imagen del
   polgono resultante en este plano rellenar el polgono cuando se dibuje
   en pantalla.

   Nos referimos a pixels en el plano de la textura como texels. Cada texel
   es un bloque, n slo un punto, y los nmeros enteros de u y v se
   refieren a la esquina superior izquierda del texel. Esto tiene varias
   implicaciones. Si quiere dibujar un polgono rectangular y aplicar una
   textura de 32x32 sobre l, debe usar las coordenadas de textura (0,0),
   (0,32), (32,32) y (32,0), asumiendo que los vrtices son especificados en
   rden antihorario. La textura ser aplicada perfectamente sobre el
   polgono. No obstante, note que si ajustamos u=32, la ltima columna de
   texels que se vern en la pantalla sern los que estn en u=31, y lo
   mismo ocurre para v. Esto es porque las coordenadas se refieren a la
   esquina superior izquierda de los texels. En efecto, las coordenadas de
   textura por la derecha y por abajo son exclusivas.

   Aqu hay otro punto interesante. Si tiene dos polgonos juntos que
   comparten dos vrtices (como las dos partes de una pieza de cartn
   doblada), y quiere aplicar sobre ellos una textura contnua, los valores
   u y v de los vrtices que estn en la junta sern iguales para ambos
   polgonos. Por ejemplo, si ambos son rectangulares, un polgono usar
   (0,0), (0,32), (32,32) y (32,0), y el otro usar (32,0), (32,32), (64,32)
   y (64,0). Esto aplicar la textura perfectamente.

   Por supuesto puede usar nmeros con decimales para u y v indicando puntos
   que estn parcialmente en un texel. Adems, dado que el plano de la
   textura es infinito, puede especificar valores mayores que el tamao de
   la textura. Esto puede ser usado para repetir la textura varias veces
   sobre el polgono.
   
   El valor c especifica el color del vrtice, y es interpretado de forma
   diferente por los modos de render.

   El parmetro type especifica el modo de render, y puede ser cualquiera de
   los siguientes:

   POLYTYPE_FLAT:
      Un simple polgono con sombreado plano, que toma el color del valor c
      del primer vrtice. Este tipo de polgono es afectado por la funcin
      drawing_mode(), por lo que puede ser usado para renderizar polgonos
      transparentes o XOR.

   POLYTYPE_GCOL:
      Un polgono con un color de sombreado goraud. Los colores de cada
      vrtice son tomados del valor c, e interpolados a travs del polgono.
      Esto es muy rpido, pero slo funcionar en modos de 256 colores si su
      paleta tiene un suave gradiente de colores. En modos truecolor
      interpreta el color como valor empaquetado en formato directo de
      hardware producido por la funcin makecol().

   POLYTYPE_GRGB:
      Un polgono con sombreado goraud que interpola tripletes RGB en vez de
      un solo color. En modos de 256 colores usa la tabla global rgb_map
      para convertir el resultado a color de 8 bits, por lo que slo puede
      ser usado despus de que haya creado una tabla de mapa de colores. Los
      colores para cada vrtice son tomados del valor c, que es interpretado
      como un triplete RGB de 24 bits (0xFF0000 es rojo, 0x00FF00 es verde y
      0x0000FF es azul).

   POLYTYPE_ATEX:
      Un polgono con textura afn. Esto dibuja la textura a travs del
      polgono con una simple interpolacin 2d lineal, que es rpida pero
      matemticamente incorrecta. Puede estar bien si el polgono es pequeo
      o plano hacia la cmara, pero como no cuenta con la acortacin de
      perspectiva, puede producir extraos artefactos movidos en la textura.
      Para ver lo que quiero decir, ejecuta test.exe y mire lo que pasa con
      el test polygon3d() cuando hace un zoom muy cerca del cubo.

   POLYTYPE_PTEX:
      Un polgono texturizado con correccin de perspectiva. Esto usa el
      valor z de la estructura del vrtice as como las coordenadas u/v, por
      lo que las texturas se ven correctamente independientemente del ngulo
      de visualizacin. Ya que esto envuelve clculos de divisin en al
      bucle interior de la texturizacin, este modo es mucho ms lento que
      POLYTYPE_ATEX, y usa coma flotante, por lo que ser muy lento en
      cualquier cosa peor que un Pentium (incluso con una FPU, un 486 no es
      capaz de mezclar divisin de coma flotante con otras operaciones de
      enteros tal y como puede hacer un Pentium).

   POLYTYPE_ATEX_MASK:
   POLYTYPE_PTEX_MASK:
      Como POLYTYPE_ATEX and POLYTYPE_PTEX, pero los pixels a cero de la
      textura son ignorados, permitiendo que la textura sea transparente.

   POLYTYPE_ATEX_LIT:
   POLYTYPE_PTEX_LIT:
      Como POLYTYPE_ATEX y POLYTYPE_PTEX, pero la tabla global color_map
      (para modos de 256 colores) o la funcin de fundido (para modos
      truecolor no-MMX) es usada para fundir la textura con el nivel de luz
      tomado del valor c en la estructura del vrtice. Esto slo puede ser
      usado despus de que haya creado una tabla de mapa de color o
      funciones de fundido!

   POLYTYPE_ATEX_MASK_LIT:
   POLYTYPE_PTEX_MASK_LIT:
      Como POLYTYPE_ATEX_LIT y POLYTYPE_PTEX_LIT, pero los pixels a cero de
      la textura son ignorados, permitiendo que la textura sea transparente.

   POLYTYPE_ATEX_TRANS:
   POLYTYPE_PTEX_TRANS:
      Renderiza texturas translcidas. Son aplicables todas las reglas
      generales de dibujado translcido. No obstante, estos modos tienen una
      limitacin: slo funcionan con bitmaps en memoria o con memoria de
      vdeo lineal (no con video por bancos). Ni si quiera lo intente en
      estos casos, ya que las funciones no realizan chequeos y su programa
      morir horriblemente (o como mnimo dibujar mal las cosas).

   POLYTYPE_ATEX_MASK_TRANS:
   POLYTYPE_PTEX_MASK_TRANS:
      Como POLYTYPE_ATEX_TRANS y POLYTYPE_PTEX_TRANS, pero los pixels a
      cero de la textura son ignorados.

   Si el bit CPU_MMX de la variable global cpu_capabilities est activado,
   las rutinas GRGB y *LIT truecolor sern optimizadas usando instrucciones
   MMX. Si el bit CPU_3DNOW est activado, las rutinas truecolor PTEX*LIT
   tomarn ventaja de la extensin de CPU 3DNow!.

   Usar rutinas MMX para *LIT tiene un efecto secundario: normalmente (sin
   MMX), estas rutinas usan las funciones de fundido y otras funciones de
   luz, creadas con set_trans_blender() o set_blender_mode(). Las versiones
   MMX slo usan el valor RGB que se pasa a set_trans_blender() y hacen la
   interpolacin lineal internamente. Por esta razn, un nuevo conjundo de
   funciones de fundido que se pasa a set_blender_mode() es ignorado.

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);
   Dibuja tringulos en 3d, usando las estructuras de vrtices de punto fijo
   o coma flotante. A diferencia de quad3d[_f], las funciones triangle3d[_f]
   no envuelven polygon3d[_f]. Las funciones triangle3d[_f] usan sus propias
   rutinas para determinar los grados del gradiente. Por esto,
   triangle3d[_f](bmp, type, tex, v1, v2, v3) es ms rpido que
   polygon3d[_f](bmp, type, tex, 3, v[]).

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);
   Dibuja cuadrilteros en 3d, usando las estructuras de vrtices de punto
   fijo o coma flotante. Esto es equivalente a llamar
      polygon3d(bmp, type, tex, 4, v[]);
   o
      polygon3d_f(bmp, type, tex, 4, v[]);

int clip3d_f(int type, float min_z, float max_z, int vc,
             V3D_f *vtx[], V3D_f *vout[], V3D_f *vtmp[], int out[]);
   Recorta el polgono dado en vtx. vc es el nmero de vrtices, el
   resultado va en vout, y vtmp y out son necesarios para uso interno. Los
   punteros en vtx, vout y vtmp deben apuntar a estructuras V3D_f vlidas.
   Como en el proceso de recorte pueden aparecer nuevos vrtices, el tamao
   de vout, vtmp y out debera ser al menos vc * (1.5 ^ n), donde n es el
   nmero de planos de corte (5 o 6), y '^' denota "elevado a la". El frustum
   (volmen visualizado) est definido por -z<x<z, -z<y<z,
   0<min_z<z<max_z. Si max_z<=min_z, el recorte z<max_z no se
   hace. Como puede ver, el recorte se realiza en el espacio de la cmara,
   con la perspectiva en mente, por lo que esta rutina debera ser llamada
   despues de aplicar la matriz de cmara, pero antes de la proyeccin de
   perspectiva. La rutina interpolar correctamente u, v, y c en la
   estructura de vrtices. Sin embargo, esto no est previsto para GCOL en
   profundidades de color high/truecolor.

int clip3d(int type, fixed min_z, fixed max_z, int vc,
           V3D *vtx[], V3D *vout[], V3D *vtmp[], int out[]);
   Versin de punto fijo de clip3d_f(). Esta funcin se debera usar con
   cuidado, dad la precisin limitada de la aritmtica de punto fijo, y las
   altas posibilidades de errores por redondeo: el cdigo de punto flotante
   es mejor en la mayora de situaciones.

Un Z-buffer almacena la profundidad de cada pixel dibujado en una pantalla.
Cuando un objeto 3d es renderizado, la profundidad de cada pixel es
comparada con el valor ya almacenado en el Z-buffer: si el pixel es ms
cercano se dibuja, en caso contrario se ignora.

No hace falta ordenar los polgonos. No obstante, sigue siendo til ignorar
los polgonos que no estn de cara a la cmara, ya que as se previene la
comparacin de muchos polgonos ocultos contra el Z-buffer. El render
mediante Z-buffer es el nico algoritmo soportado por Allegro que resuelve
directamente la interseccin entre figuras (mire por ejemplo exzbuf.c). El
precio que hay que pagar son unas rutinas ms complejas (y ms lentas).

Los polgonos con Z-buffer son por diseo una extensin de los estilos de
render normales POLYTYPE_*. Slo hay que hacer una OR entre POLYTYPE y el
valor POLYTYPE_ZBUF, y las rutinas normales como polygon3d(), polygon3d_f(),
quad3d(), etc, renderizarn polgonos con Z-buffer.

Ejemplo:

   polygon3d(bmp, POLYTYPE_ATEX | POLYTYPE_ZBUF, tex, vc, vtx);


Por supuesto, las coordenadas z deben ser vlidas sin importar el estilo de
render.

El procedimiento de render con Z-buffer parece un render con doble buffer.
Debera seguir los siguientes pasos: crear el Z-buffer al comienzo de su
programa y hacer que la librera lo use mediante set_zbuffer(). Entonces,
por cada frame, borre el Z-buffer y dibuje polgonos con POLYTYPE_* |
POLYTYPE_ZBUF para finalmente destruir el Z-buffer al finalizar su programa.

Notas sobre los renders con Z-buffer:

A diferencia de las renderizaciones normales con POLYTYPE_FLAT, el render
con Z-buffer no usa la rutina hline(). Por lo tanto, DRAW_MODE no tiene
efecto sobre el resultado.

Las rutinas *LIT* funcionan del modo tradicional - a travs del conjunto de
rutinas de blending.

Todas las rutinas con Z-buffer son mucho ms lentas que sin Z-buffer (todas
usan el coprocesador para interpolar y comprobar valores 1/z).

ZBUFFER *create_zbuffer(BITMAP *bmp);
   Crea el Z-buffer usando el tamao del BITMAP que est planeando usar para
   dibujar sus polgonos. Se pueden definir varios Z-buffers, pero slo se
   puede usar uno a la vez, por lo que debe usar set_zbuffer() para elegir
   cul ser activo.

ZBUFFER *create_sub_zbuffer(ZBUFFER *parent, int x, int y, int width, int height);
   Crea un sub-z-buffer, es decir, un z-buffer que comparte memoria de
   dibujado con un z-buffer ya existente, pero posiblemente con un tamao
   diferente. Son aplicables las mismas reglas que con los sub-bitmaps: la
   anchura y altura pueden extenderse fuera de los bordes del z-buffer padre
   (sern recortados), pero el punto de origen debe estar en una regin del
   padre.

   Cuando dibuje con z-buffer en un bitmap, la esquina superior izquierda
   del bitmap siempre est alineada con la esquina superior izquierda del
   z-buffer actual. Por lo que esta funcin es til principalmente si quiere
   dibujar en un sub-bitmap y usar el rea correspondiente del z-buffer. En
   otros casos, ej, si quiere dibujar en un sub-bitmap de la pantalla (y no
   en otras partes de la pantalla), normalmente querr crear un z-buffer
   normal (no un sub-z-buffer) del tamao de la pantalla. No necesita crear
   un z-buffer del tamao de la pantalla virtual y entonces un sub-z-buffer
   de ste.

void set_zbuffer(ZBUFFER *zbuf);
   Hace que un Z-buffer sea el activo. Este deber haber sido creado
   previamente mediante create_zbuffer().

void clear_zbuffer(ZBUFFER *zbuf, float z);
   Escribe z en el Z-buffer (0 significa muy lejos). Esta funcin debe ser
   usada para iniciar el Z-buffer antes de cada frame. Realmente, las
   rutinas de bajo nivel comparan la profundidad del pixel actual con 1/z:
   por ejemplo, si quiere recortar polgonos ms lejanos de 10, debe usar:
   clear_zbuffer(zbuf, 0.1);

void destroy_zbuffer(ZBUFFER *zbuf);
   Destruye el Z-buffer cuando haya finalizado.

Allegro provee dos mtodos simples para quitar caras ocultas:

   Z-buffering - (vea ms arriba)

   Algoritmos scan-line - a lo largo de cada lnea de su pantalla, mantiene
   informacin sobre el polgono "en el que est" y cul es el ms cercano.
   Este estado cambia slamente cuando la lnea cruza el borde de un
   polgono. Por lo que debe mantener una lista de bordes y polgonos. Y
   debe ordenar los bordes para cada scanline (esto es contrarrestado
   manteniendo el rden del scanline previo - no cambiar mucho). La GRAN
   ventaja es que slo dibuja cada pixel una vez. Si tiene muchos polgonos
   que se solapan, puede obtener increbles velocidades comparadas con
   cualquiera de los algoritmos previos. Este algoritmo es cubierto por
   las rutinas *_scene.


El render de escenas sigue los siguientes pasos aproximdamente:

   Iniciar la escena (ajustar el rea de recorte, limpiar el bitmap,
   dibujar un fondo, etc).

   Llame clear_scene().

   Transformar todos sus puntos al espacio de la cmara.

   Recortar polgonos.

   Proyectar con persp_project() o persp_project_f().

   "Dibujar" polgonos con scene_polygon3d() y/o scene_polygon3d_f().
   Esto realmente no dibuja nada, slo inicializa las tblas.

   Renderizar todos los polgonos definidos previamente en el bitmap
   con render_scene().

   Dibujar grficos no tridimensionales.

   Mostrar el bitmap (blit a la pantalla, cambio de pgina, etc).


Por cada linea horizontal del rea de visualizacin se usa una lista
ordenada de bordes para saber qu polgonos "estn dentro" y cules estn
cerca. Se usa coherencia vertical - la lista de bordes es ordenada a
partir de la anterior - no cambiar mucho. Las rutinas de render de escenas
usan las mismas rutinas de bajo nivel que polygon3d().

Notas del render de escena:

   A diferencia de polygon3d(), scene_polygon3d() requiere coordenadas z
   vlidas para todos los vrtices, indiferentemente del estilo de render
   (en contraste con polygon3d(), que slo usa coordenadas z para *PTEX*).

   Todos los polgonos pasados a scene_polygon3d() deben ser proyectados
   con perspectiva.

   Tras usar render_scene(), el modo es ajustado a SOLID.

Usar muchos polgonos con mscara reduce el rendimiento, porque cuando se
encuentra un polgono con mscara en primera linea de visin, los polgonos
que estn detrs deben ser dibujados tambin. Lo mismo es aplicable a
polgonos FLAT dibujados con DRAW_MODE_TRANS.

El render con Z-buffer tambin funciona con el render de escenas. Puede ser
til si tiene algunos polgonos que se interseccionan, pero la mayora de
los polgonos pueden ser renderizados sin problemas usando el algoritmo
normal de ordenado de scanlines. Igual que antes: simplemente haga una OR
del POLYTIPE con POLYTYPE_ZBUF. Adems, tiene que limpiar el z-buffer al
comienzo del frame. Ejemplo:

   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);
   Reserva memoria para una escena, nedge y npoly son sus estimaciones de
   cuntas aristas y polgonos renderizar (no puede salirse del lmite que
   especifica aqu). Si usa los mismos valores en llamadas sucesivas, el
   espacio ser reusado (no nuevos malloc()).

   La memoria reservada es algo menor que 150 * (nedge + npoly) bytes.
   Devuelve cero con xito, o negativo si no se pudo reservar la memoria.

void clear_scene(BITMAP *bmp);
   Inicializa la escena. El bitmap es donde renderizar sus grficos.

void destroy_scene();
   Libera la memoria previamente reservada por create_scene.

int scene_polygon3d(int type, BITMAP *texture, int vc, V3D *vtx[]);
int scene_polygon3d_f(int type, BITMAP *texture, int vc, V3D_f *vtx[]);
   Pone un polgono en la lista de render. Realmente no renderiza nada en
   este momento. Debe llamar esta funcin entre clear_scene() y
   render_scene().

   Los argumentos son iguales que para polygon3d(), excepto por el parmetro
   de bitmap que falta. Se usar el que indic mediante clear_scene().

   A diferencia de polygon3d(), los polgonos pueden ser cncavos o estar
   interseccionados. Las figuras que penetran en otras pueden salir bien,
   pero no son manejadas realmente por este cdigo.

   Note que slo se almacena un puntero a la textura, por lo que debera
   mantenerla en memoria hasta render_scene(), donde ser usada.

   Ya que el estilo FLAT es implementado con la funcin de bajo nivel
   hline(), el estilo FLAT est sujeto a DRAW_MODE. Todos los modos son
   vlidos. Junto con el polgono, el modo ser almacenado para el momento
   del render, y tambin otras variables relacionadas (puntero al mapa de
   color, puntero al patron, ancla, valores de blending).

   El valor de los bits CPU_MMX y CPU_3DNOW de la variable global
   cpu_capabilities afectar la eleccin de la rutina de bajo nivel en
   ensamblador que ser usada por render_scene() con este polgono.

   Devuelve cero con xito o negativo si no ser renderizado debido a que
   falta la rutina de render apropiada.

void render_scene();
   Renderiza toda la escena creada con scene_polygon3d() en el bitmap que
   pas a clear_scene(). El render se realiza una linea a cada vez, sin
   procesar dos veces el mismo pixel.

   Note que entre clear_scene() y render_scene() no debera modificar el
   rectngulo de recorte del bitmap destino. Por razones de velocidad,
   debera ajustar el rectngulo de recorte al mnimo.

   Tenga en cuenta tambin que las texturas pasadas a scene_polygon3d() son
   almacenadas como punteros y sern usadas en render_scene().

extern float scene_gap;
   Este nmero (valor por defecto = 100.0) controla el comportamiento del
   algoritmo de ordenado en z. Cuando un borde est muy cerca del plano de
   otro polgono, hay un intervalo de incertidumbre en el cual no se puede
   determinar qu objeto es visible (qu z es ms pequea). Esto es debido
   a errores numricos acumulativos para los bordes que han sufrido
   bastantes transformaciones e interpolaciones.

   El valor por defecto significa que si los valores 1/z (en espacio
   proyectado) difieren slo en 1/100 (uno por ciento), sern considerados
   iguales y el eje x de los planos ser usado para saber qu plano est
   acercndose mientras nos movemos hacia la derecha.

   Valores mayores significan mrgenes menores, e incrementan la posibilidad
   de confundir planos/bordes realmente adyacentes. Valores menores
   significan mrgenes mayores, e incrementan la posibilidad de confundir un
   polgono cercano con uno adyacejte. El valor de 100 est cercano a lo
   ms ptimo. No obstante, el valor optimo oscila con diferentes
   resoluciones, y puede ser dependiente de la aplicacin. Est aqu para
   que lo pueda ajustar al mximo.



===============================================================
============ 18 Transparencias y dibujo con patrn ============
===============================================================

void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor);
   Ajusta el modo de dibujo grfico. Esto slo afecta a las rutinas
   geomtricas como putpixel, lines, rectangles, circles, polygons,
   floodfill, etc, y no a la salida de texto, blits o dibujado de sprites.
   El modo debera ser uno de los siguientes valores.

      DRAW_MODE_SOLID               - por defecto, dibujado slido
      DRAW_MODE_XOR                 - dibujado or-exclusivo
      DRAW_MODE_COPY_PATTERN        - rellenado con patrn multicolor
      DRAW_MODE_SOLID_PATTERN       - rellenado con patrn de un solo color
      DRAW_MODE_MASKED_PATTERN      - rellenado con patrn enmascarado
      DRAW_MODE_TRANS               - fundido de color translcido

   En DRAW_MODE_XOR, los pixels son escritos en el bitmap con una operacin
   or-exclusiva en vez de con la copia simple, por lo que dibujar la misma
   figura dos veces la borrar. Como esto requiere tanto leer como escribir
   en el bitmap de memoria, el dibujado xor es mucho ms lento que el modo
   normal.

   Con los modos con patrn, usted indica un bitmap de patrn que ser
   dibujado sobre la superficie de la figura. Allegro almacena un puntero a
   este bitmap en vez de una copia, por lo que no debe destruir el bitmap
   mientras sea usado como patrn. El ancho y alto del patrn debe ser un
   mltiplo de dos, pero pueden ser diferentes, es decir, un patrn de 64x16
   est bien, pero uno de 17x3 no. El patrn ser repetido en una rejilla
   comenzando en el punto (x_anchor, y_anchor). Normalmente debera pasar
   cero para estos valores, lo que le dejar dibujar varias figuras y que
   sus patrones se junten en los bordes. Un alineamiento de cero puede sin
   embargo ser peculiar cuando mueva una figura con patrn por la pantalla,
   porque la figura se mover, pero el patrn no, por lo que en algunas
   situaciones quizs le interese alterar las posiciones del ancla (anchor).

   Cuando selecciona DRAW_MODE_COPY_PATTERN, los pixels simplemente son
   copiados del bitmap de patrn al bitmap destino. Esto le permite usar
   patrones multicolor, y significa que el color que pase a la rutina de
   dibujado es ignorado. Este es el ms rpido de los modos con patrn.

   En DRAW_MODE_SOLID_PATTERN, cada pixel del patrn es comparado con el
   color de mscara (cero en modos de 256 colores, rosa fucsia en modos
   truecolor). Si el pixel del patrn es slido, un pixel del color que pas
   a la rutina de dibujado es escrito en el bitmap destino, de otro modo
   escribe un cero. El patrn es por esto tratado como una mscara
   monocroma, que le permite usar el mismo patrn para dibujar diferentes
   figuras con colores diferentes, pero previene el uso de patrones
   multicolores.

   DRAW_MODE_MASKED_PATTERN es casi lo mismo que DRAW_MODE_SOLID_PATTERN,
   pero los pixels enmascarados son ignorados en vez de copiados como cero,
   por lo que el fondo se ver a travs de los agujeros.

   En DRAW_MODE_TRANS, la tabla global color_map o las funciones de fundido
   se usan para sobreimprimir pixels encima de la imgen existente. Esta slo
   debe usarse despus de haber constudo la tabla de mapeo de color (para
   modos de 256 colores) o las funciones de fundido (para modos truecolor).
   Dado que debe leer y escribir en la memoria del bitmap, el dibujado
   transparente es muy lento si dibuja directamente en la memora de vdeo,
   as que siempre que sea posible debera dibujar en bitmaps de memora.

void xor_mode(int on);
   Esto es un atajo para activar o desactivar el modo de dibujado xor.
   Llamar xor_mode(TRUE) es equivalente a drawing_mode (DRAW_MODE_XOR, NULL,
   0, 0); Llamar xor_mode(FALSE) es equivalente a
   drawing_mode (DRAW_MODE_SOLID, NULL, 0, 0);

void solid_mode();
   Esto es un atajo para seleccionar el dibujado slido. Es equivalente a
   llamar drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);

En modos de vdeo con paleta, la translucidez y la iluminacin son
implementadas con una tabla precalculada de 64k, que contiene el resultado
de la combinacin de cualquier color c1 con c2. Tiene que crear esta tabla
antes de usar cualquiera de las rutinas de iluminacin o translucidez.
Dependiendo de cmo se crea tabla, ser posible hacer un rango diferente de
efectos. Por ejemplo, la translucidez se puede implementar usando un color
intermedio entre c1 y c2 como resultado de su combinacin. La iluminacin se
consigue tratando uno de los colores como nivel de luz (0-255) en vez de
como color, y creando la tabla apropiadamente. Un rango de efectos
especializados es posible, si por ejemplo sustituye cualquier color con otro
color haciendo los colores individuales de origen o destino totalmente
slidos o invisibles.

Las tablas de color pueden ser precalculadas con la utilidad colormap, o
generadas en tiempo real. La estructura COLOR_MAP se define as:

   typedef struct {
      unsigned char data[PAL_SIZE][PAL_SIZE];
   } COLOR_MAP;

extern COLOR_MAP *color_map;
   Puntero global a una tabla de color. Esto debe ser ajustado antes de usar
   cualquiera de las funciones de dibujado translcido o iluminado en modos
   de 256 colores!

void create_light_table(COLOR_MAP *table, const PALETTE pal,
                        int r, g, b, void (*callback)(int pos));
   Llena la tabla de mapeo de color especificada con los datos precalculados
   necesarios para hacer efectos de translucidez con la paleta especificada.
   Cuando se combinan los colores c1 y c2 con esta tabla, c1 se trata como
   un nivel de luz desde 0 a 255. Con un nivel de luz de 255 la tabla
   devolver el color c2 sin cambios, con un nivel de luz 0 devolver el
   valor r,g,b que especifque a la funcin, y con niveles de luz intermedios
   devolver un color intermedio. Los valores r,g y b estn entre 0-63. Si
   la funcin callback no es NULL, se la llamar 256 veces durante el
   clculo, permitindole mostrar un indicador de progreso.

void create_trans_table(COLOR_MAP *table, const PALETTE pal,
                        int r, g, b, void (*callback)(int pos));
   Rellena la tabla de color especificada con los datos precalculados
   necesarios para hacer efectos de translucidez con la paleta especificada.
   Cuando se combinan los colores c1 y c2 en esta tabla, el resultado ser un
   color intermedio entre los dos. Los valores r, g, b que especifique son la
   solidez de cada componente de color, desde 0 (totalmente transparente)
   hasta 255 (totalmente slido). Para una solidez del 50%, pasa 128. Esta
   funcin trata el color origen #0 como un caso especial, dejando el destino
   sin cambiar siempre que se encuentre un pixel del color cero, para que los
   sprites con mscara puedan ser dibujados correctamente. Si la funcin
   callback no es NULL, ser llamada 256 veces durante el clculo,
   permitindole ensear un indicador de progreso.

void create_color_table(COLOR_MAP *table, const PALETTE pal,
                        void (*blend)(PALETTE pal, int x, int y, RGB *rgb),
                        void (*callback)(int pos));
   Llena la tabla de mapeo de color con datos precalculados necesarios
   para poder hacer efectos propios con la paelta especificada, llamando a la
   funcin de fundido para determinar los resultados de cada combinacin de
   color. A su rutina de fundido se le pasar un puntero a la paleta y los
   dos colores que van a ser combinados, y debera devolver el resultado
   deseado en una estructura RGB con formato 0-63. Entonces Allegro buscar
   en la paleta aqul color que mejor encaje con el que pidi, por lo que no
   importa si la paleta no tiene un color que encaje exactamente. Si la
   funcin callback no es NULL, se le llamar 256 veces durante el clculo,
   permitindole que muestre un indicador de progreso.

void create_blender_table(COLOR_MAP *table, const PALETTE pal,
                          void (*callback)(int pos));
   Llena la tabla de mapeo de color especificada con datos precalculados
   para hacer un equivalente "paletizado" de cualquiera de los modos de
   fundido truecolor que est actualmente seleccionado. Despus de llamar a
   set_trans_blender(), set_blender_mode() o cualquiera de las otras rutinas
   de modo de fundido, puede usar esta funcin para crear un tabla de mapeo
   de 8 bits que tendr los mismos resultados que el modo de fundido de 24
   bits que tenga seleccionado.

En los modo de video truecolor, la translucidez y la iluminacin estn
implementadas por una funcin de fundido de la forma:

   unsigned long (*BLENDER_FUNC)(unsigned long x, y, n);

Esta rutina toma dos colores como parmetros, los descompone en sus
componenetes rojo, verde y azul, los combina acorde con el valor de
interpolacin n, y entonces fusiona de nuevo el resultado en un solo valor
de color, que devuelve.

Como estas rutinas se pueden usar desde diferentes profundidades de color,
hay tres callbacks, una para usar con pxels de 15 bits (5.5.5), una para
pxels de 16 bits (5.6.5), y otra para pxels de 24 bits (8.8.8), que puede
compartirse entre el cdigo de 24 y 32 bits dado que el empaquetamiento de
bits es el mismo.

void set_trans_blender(int r, int g, int b, int a);
   Selecciona el conjunto de rutinas de fundido por defecto, que hacen una
   interpolacin lineal simple entre los colores fuente y destino. Cuando se
   llama a una funcin de dibujo translcido, el parmetro alfa ajustado por
   esta rutina se usa como factor de interpolacin, que controla la solidez
   del dibujado (de 0 a 255). Cuando una funcin de dibujo iluminado de
   es llamada, el valor alfa se ignora, y se usa el color pasado a la
   funcin de sprite para seleccionar un nivel alfa. La rutina de fundido
   se usar para interpolar entre el color del sprite y los valores RGB que
   se le pasaron a esta funcin (en un rango de 0 a 255).

void set_alpha_blender();
   Activa el modo de fundido especial de canal-alfa, que se usa para dibujar
   sprites RGBA de 32 bits. Despus de llamar a esta funcin, puede usar
   draw_trans_sprite() o draw_trans_rle_sprite() para dibujar una imagen
   de 32 bits en un otra hicolor o truecolor. Los valore alfa se tomarn
   directamente del grfico origen, asq ue puede variar la solidez de cada
   parte de la imagen. Sin embargo, no puede usar ninguna de las funciones
   normales de translucidez mientras este modo est activo, as que debera
   volver a uno de los modos normales de fundido (p.ej. set_trans_blender())
   antes de dibujar otra cosa que no sean sprites en RGBA de 32 bits.

void set_write_alpha_blender();
   Activa el modo especial de edicin de canal-alfa, que se usa para dibujar
   canales alfa encima de un sprite RGB existente, para transformarlo en una
   imagen en formato RGBA. Despus de llamar a esta funcin, puede ajustar
   el modo de dibujo a DRAW_MODE_TRANS y entonces escribir valores de color
   (de 0 a 255) en una imgen de 32 bits. Esto dejar los valores de color
   igual, pero alterar el alfa con los valores que est escribiendo. Despus
   de activar este modo tambin puede usar draw_trans_sprite() para
   superponer una mascara alfa de 8 bits encima de un sprite existente de 32
   bits.

void set_add_blender(int r, int g, int b, int a);
   Activa un modo de fundido de color para combinar pxels truecolor
   iluminados o translcidos.

void set_burn_blender(int r, int g, int b, int a);
   Activa un modo de fundido "chamuscado" para combinar pxels truecolor
   iluminados o translcidos. Aqu el brillo de los colores de la imagen
   origen reduce el brillo de la imagen destino, oscureciendola.

void set_color_blender(int r, int g, int b, int a);
   Activa  un modo de fundido de color para combinar pxels truecolor
   iluminados o translcidos. Aplica slo el tono y saturacin de la imagen
   origen a la imagen destino. La luminosidad de la imagen destino no queda
   afectada.

void set_difference_blender(int r, int g, int b, int a);
   Activa el modo de fundido por diferencia para combinar pxels truecolor
   translcidos o iluminados. Esto crea una imgen que tiene colores
   calculados por la diferencia entre los colores fuente y destino.

void set_dissolve_blender(int r, int g, int b, int a);
   Activa un modo de fundido por disolucin para combinar pxels truecolor
   translcidos o iluminados. Aleatoriamente, reemplaza los colores de
   algunos pxels de la imagen destino con los correspondientes de la
   imgen origen. El nmero de pixels reeemplazados depende del valor alpha
   (cuanto ms alto sea el valor, ms pixels se reemplazarn; va pillando la
   idea :)

void set_dodge_blender(int r, int g, int b, int a);
   Activa un mode de fundido "trucado" para combinar pxels truecolor
   iluminados o translcidos. La claridad de colores en la imgen origen
   ilumina los colores de la imagen destino. El mayor efecto se consigue con
   el blanco; el negro no tiene ningn efecto.

void set_hue_blender(int r, int g, int b, int a);
   Activa un modo de fundido por tono para combinar pxels truecolor
   iluminados o translcidos. ste aplica el tono del origen al destino.

void set_invert_blender(int r, int g, int b, int a);
   Activa el modo de fundido inverso para combinar pxels truecolor
   iluminados o translcidos. Funde el color inverso (o negativo) del
   origen con el de destino.

void set_luminance_blender(int r, int g, int b, int a);
   Activa el modo de fundido de iluminacin para combinar pxels truecolor
   iluminados o translcidos. Aplica la ilumincacin del origen al destino.
   El color de la destinacin no queda afectado.

void set_multiply_blender(int r, int g, int b, int a);
   Activa un modo de fundido por multiplicacin para combinar pxels
   truecolor iluminados o translcidoz. Combina las imgenes origen y
   destino, multiplicando los coloroes para producir un color ms oscuro.
   Si el color se multiplica por blanco no cambia; cuando se multiplica
   por negro se vuelve negro.

void set_saturation_blender(int r, int g, int b, int a);
   Activa un modo de fundido de saturacin para combinar pxels truecolor
   iluminados o translcidos. Aplica la saturacin del origen a la imagen
   destino.

void set_screen_blender(int r, int g, int b, int a);
   Activa un modo de fundido de pantalla para combinar pxels truecolor
   iluminados o translcidos. Este modo de fundido ilumina el color de la
   imagen destino multiplicando el color inverso del origen con el color
   destino. Es ms o menos el opuesto al modo de fundido por multiplicacin.

void set_blender_mode(BLENDER_FUNC b15, b16, b24, int r, g, b, a);
   Especifca un conjunto de rutinas propias de fundido en truecolor, que
   pueden ser usadas para implementar cualquier modo de interpolacin que
   necesite. Esta funcin comparte un nico fundido entre los modos de 24 y
   32 bits.

void set_blender_mode_ex(BLENDER_FUNC b15, b16, b24, b32, b15x, b16x, b24x,
                         int r, g, b, a);
   Como set_blender_mode(), pero le permite especificar un conjunto ms
   completo de rutinas de fundido. Las rutinas b15, b16, b24 y b32 se
   usan cuando se vayan a dibujar pxels en destinos con el mismo formato,
   meintras que b15x, b16x y b24x las usan draw_trans_sprite() y
   draw_trans_rle_sprite cuando van adibujar imgenes RGBA en un destino
   que tiene otro formato. Estos fundidos se les pasar un parmetro x de
   32 bits, junto con un valor y de una profundidad diferente de color, y
   debe hacer algo sensible como respuesta.



==============================================================
============ 19 Conversiones de formatos de color ============
==============================================================

En general, Allegro est diseada para usarse slo con una profundidad de
color a la vez, as que slo llamar una vez a set_color_depth() y entonces
almacenar todos sus bitmaps en el mismo formato. Si quiere mezclar
diferentes formatos de pxel, puede usar create_bitmap_ex() en vez de
create_bitmap(), y llamar a bitmap_color_depth() para pedir el formato de la
imagen en cuestin. La mayora de las rtinas grficas requieren que todos
sus parmetros de entrada estn en el mismo formato (p.ej. no puede expandir
un bitmap origen de 15 bits en un destino de 24 bits), pero hay cuatro
excepciones: blit() y las rutinas de rotacin puede copiar entren bitmaps de
cualquier formato, convirtiendo los datos cuando se requiera, draw_sprite()
puede dibujar imgenes origen de 256 colores en destion de cualquier formato,
draw_character() _siempre_ usa un bitmap origen de 256 colores, sea cual sea
el formato de destino, las funciones draw_trans_sprite() y
draw_trans_rle_sprite() son capaces de dibujar imgenes de 32 bits RGBA en un
destino hicolor o truecolor, siempre y cuando llame antes a
set_alpha_blender(), y la funcin draw_trans_sprite() es capaz de dibujar una
imagen con 8 bits de canal alfa encima de una imagen ya existente de 32 bits,
siempre y cuando llame antes a set_write_alpha_blender().

Expandir un bitmap origen de 256 colores en un bitmap destino truecolor es
muy rpido (obviamente deber ajustar la paleta de colores correcta antes
de la conversin!). Convertir entre diferentes formatos truecolor es algo
ms lento, y reducir imgenes truecolor a 256 puede ser muy lento (puede
acelerarse si crea una tabla global rgb_map antes de realizar la
conversin).

int bestfit_color(const PALLETE pal, int r, int g, int b);
   Busca en la paleta el valor ms parecido al color requerido, que es
   especificado en el formato hardware de la VGA 0-63. Normalmente debera
   llamar makecol8() en vez de esto, pero esta funcin de bajo nivel puede
   ser til si necesita usar una paleta de colores diferente a la
   seleccionada, o si no quiere usar la tabla precalculada rgb_map a
   propsito.

extern RGB_MAP *rgb_map;
   Para acelerar la reduccin de valores RGB a 8 bits, Allegro usa una
   tabla precalculada de 32k (5 bits por cada componente de color). Debe
   crear esta tabla antes de usar las rutinas de sombreado gouraud, y si
   est presente, la tabla acelerar vastamente la funcin makecol8(). Las
   tablas RGB pueden ser precalculadas con la utilidad rgbmap, o generadas
   en tiempo real. La estructura RGB_MAP est definida como:

   typedef struct {
      unsigned char data[32][32][32];
   } RGB_MAP;

void create_rgb_table(RGB_MAP *table, const PALETTE pal,
        void (*callback)(int pos));
   Llena la tabla RGB especificada con datos precalculados de la paleta
   elegida. Si la funcin callback no es NULL, ser llamada 256 veces
   durante el clculo, permitindole ensear un indicador de progreso.

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);
   Convierte valores de color entre los modos HSV y RGB. Los valores RGB van
   de 0 a 255, hue va de 0 a 360, y la saturacin y el valor van de 0 a 1.



=================================================================
============ 20 Acceso directo a la memoria de vdeo ============
=================================================================

La estructura bitmap es as:

   typedef struct BITMAP
   {
      int w, h;               - tamao del bitmap en pixels
      int clip;               - no-cero si recortar est activado
      int cl, cr, ct, cb;     - lmites de recorte izquierdo, derecho, superior
                                e inferior
      int seg;                - segmento para uso con los punteros a lnea
      unsigned char *line[];  - punteros al comienzo de cada lnea
   } BITMAP;

Tambin hay otras cosas en la estructura, pero podran cambiar, y no
debera usar nada excepto lo de arriba. El rectngulo de recorte es
inclusivo arriba a la izquierda (0 permite dibujar en la posicin 0) pero
exclusivo abajo a la derecha (10 permite dibujar en la posicin 9, pero no
en la 10). Fjese que ste no es el mismo formato que el que se usa con
set_clip(), el cual toma coordenadas inclusivas para las cuatro esquinas.

Hay varios modos de conseguir acceso directo a la memoria de imagen de un
bitmap, variando en complejidad dependiendo del tipo de bitmap que use.

El modo ms simple slo servir si trabaja con bitmaps de memoria
(obtenidos con create_bitmap(), ficheros de datos, y ficheros de imgenes) y
sub-bitmaps de bitmaps de memoria. Esto usa una tabla de punteros char,
llamados 'line', la cual es parte de la estructura bitmap y contiene
punteros al comienzo de cada lnea de la imagen. Por ejemplo, una funcin
putpixel simple para un bitmap de memoria es:

   void memory_putpixel(BITMAP *bmp, int x, int y, int color)
   {
      bmp->line[y][x] = color;
   }

Para modos truecolor, es necesario especificar el tipo del puntero de lnea,
por ejemplo:

   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;
   }

Si quiere escribir en la pantalla y tambin en bitmaps de memoria, necesita
usar algunas macros auxiliares, porque la memoria de vdeo puede no ser
parte de su espacio de direcciones normal. Esta simple rutina funcionar para
cualquier pantalla lineal, p.ej unos framebuffers lineales de VESA.

   void linear_screen_putpixel(BITMAP *bmp, int x, int y, int color)
   {
      bmp_select(bmp);
      bmp_write8((unsigned long)bmp->line[y]+x, color);
   }

Para los modos truecolor debera reemplazar bmp_write8() por bmp_write16(),
bmp_write24(), o bmp_write32(), y multiplicar el desplazamiento x por el
nmero de bytes por pxel. Por supuesto hay funciones similares para leer el
valor de un pixel de un bitmap, y son bmp_read8(), bmp_read16(), bmp_read24()
y bmp_read32().

Esto, sin embargo, seguir sin funcionar en los modos de SVGA por bancos,
o en plataformas como Windows, que hacen un procesado especial dentro de
las funciones de cambio de banco. Para un acceso ms flexible a los bitmaps
de memoria, necesita llamar a las rutinas:

unsigned long bmp_write_line(BITMAP *bmp, int line);
   Selecciona la lnea de un bitmap en la que va a dibujar.

unsigned long bmp_read_line(BITMAP *bmp, int line);
   Selecciona la lnea de un bitmap de la que va a leer.

unsigned long bmp_unwrite_line(BITMAP *bmp);
   Libera el bitmap de memoria despued de que haya acabado de trabajar con
   l. Slo necesita llamar a esta funcin una vez al final de una operacin
   de dibujado, incluso si ha llamado a bmp_write_line() o bmp_read_line()
   diversas beces antes.

Estas estn implementadas como rutinas de ensamblador en lnea, por lo que no
son tan ineficientes como podran parecer. Si el bitmap no necesita cambio de
banco (ejemplo: es un bitmap de memoria, pantalla en modo 13h, etc), estas
funciones simplemente retornan bmp->line[line].

A pesar de que los bitmaps de SVGA usan bancos, Allegro permite acceso
lineal a la memoria dentro de cada scanline, por lo que slo necesita pasar
una coordenada y a estas funciones. Varias posiciones x pueden ser obtenidas
simplemente sumando la coordenada x a la direccin devuelta. El valor
devuelto es un entero largo sin signo en vez de un puntero a caracter porque
la memoria bitmap puede no estar en su segmento de datos, y necesita
acceder a l con punteros far. Por ejemplo, una funcin putpixel usando
funciones de cambio de banco es:

   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);
   }

Se dar cuenta de que Allegro tiene funciones separadas para seleccionar
los bancos de lectura y escritura. Es importante que distinga entre estos,
porque en algunas tarjetas de vdeo los bancos pueden ser seleccionados
individualmente, y en otros la memoria de vdeo es leda y escrita en
direcciones diferentes. No obstante, la vida nunca es tan simple como
desearamos que fuese (esto es verdad incluso cuando _no_ estamos hablando
de programacin de grficos :-) y por supuesto algunas tarjetas de vdeo
slo pueden proveer un banco. En stas, las funciones de lectura/escritura
se comportarn idnticamente, por lo que no debera asumir que puede leer de
una parte de la memoria de vdeo y escribir en otra al mismo tiempo. Puede
llamar bmp_read_line(), y leer lo que quiera de la lnea, entonces llamar
bmp_write_line() con el mismo o diferente valor de lnea, y escribir lo que
quiera en ella, pero no debera llamar bmp_read_line() y bmp_write_line() a
la vez y esperar poder leer una lnea y escribir en otra simultneamente.
Sera bueno si esto fuese posible, pero si lo hace, su cdigo no funcionar
en tarjetas SVGA de un banco.

Y tambin est el modo-X. Si nunca antes haba programado grficos en este
modo, probablemente no entienda esto, pero para aquellos que quieren saber
cmo Allegro trabaja con los bitmaps de pantalla del modo-X, aqu va...

Los punteros a lnea todava estn presentes, y contienen direcciones
lineales, esto es, la direccin con la cual accedes al primer pixel de la
lnea. Est garantizada la alineacin cada cuatro pixels de las direcciones,
por lo que puede fijar el plano de escritura, dividir su coordenada entre
cuatro, y aadirla al puntero de lnea. Por ejemplo, un putpixel en modo-X
es:

   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);
   }

Ah s: el truco de djgpp del nearptr. Personalmente, no me gusta demasiado
porque desactiva la proteccin de la memoria y no es portable a otras
plataformas, pero hay mucha gente que suspira por l porque puede dar acceso
directo a la memoria de pantalla via un puntero normal de C. Aviso: Este
mtodo slo funcionar con la librera djgpp, cuando est usando el modo
VGA 13h o un framebuffer lineal!

En su cdigo de inicializacin:

   #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);

Luego:

   void nearptr_putpixel(int x, int y, int color)
   {
      screenmemory[x + y*SCREEN_W] = color;
   }



=========================================
============ 21 Rutinas FLIC ============
=========================================

Hay dos funciones de alto nivel para reproducir animaciones FLI/FLC:
play_fli(), la cual lee datos directamente del disco, y play_memory_fli(),
la cual usa datos que ya estn cargados en la RAM. Aparte de las diferentes
fuentes de las que se sacan los datos, estas dos funciones se comportan de
forma idntica. Ambas dibujan la animacin en el bitmap especificado, que
debera ser normalmente screen. Los cuadros se alinearn con la esquina
superior izquierda del bitmap: si quiere posicionarlos en otra parte de la
pantalla tendr que crear un sub-bitmap y decirle al reproductor FLI que
dibuje all la animacin. Si loop est activado, el reproductor volver al
principio de la animacin cuando sta acabe, de otro modo, reproducir la
animacin una vez. Si la funcin callback no es NULL, ser llamada por cada
frame, permitindole realizar tareas en segundo plano. La rutina de callback
debe devolver cero: si retorna un valor que no es cero, el reproductor se
parar (este es el nico modo de parar una animacin que est siendo
repetida). El reproductor FLI devuelve FLI_OK si ha llegado al final del
fichero, FLI_ERROR si hubo problemas, y el valor de la funcin callback, si
fue sta la que par la reproduccin. Si necesita distinguir entre
diferentes valores de retorno, su rutina de callback debera devolver
enteros positivos, ya que FLI_OK es cero y FLI_ERROR negativo. Tome nota de
que el reproductor FLI slo funcionar si se instal el mdulo de
temporizacin, y que alterar la paleta de colores segn la del fichero de
animacin.

Ocasionalmente podra necesitar un control ms detallado sobre la
reproduccin FLI, por ejemplo si quiere sobreimprimir algn texto sobre la
animacin, o reproducirla a una velocidad diferente. Puede hacer ambas
cosas usando las funciones de bajo nivel descritas abajo.

int play_fli(const char *filename, BITMAP *bmp, int loop, int (*callback)());
   Reproduce un fichero FLI o FLC del Autodesk Animator, leyendo los datos
   del disco segn se necesiten.

int play_memory_fli(const void *fli_data, BITMAP *bmp, int loop,
           int (*callback)());
   Reproduce una animacin FLI o FLC del AutoDesk Animator, leyendo los datos
   de una copia de un fichero que se almacena en memoria. Puede obtener el
   puntero fli_data reservando un bloque de memoria con malloc y copiando el
   fichero FLI all, o importando un FLI en un fichero de datos con el
   grabber. Reproducir animaciones desde la memoria es obviamente ms rpido
   que desde disco, y es particularmente til con animaciones FLI pequeas
   que se repiten. Sin embargo, las animaciones pueden fcilmente llegar a
   ser grandes, por lo que en la mayora de los casos sera mejor que use
   play_fli().

int open_fli(const char *filename);
int open_memory_fli(const void *fli_data);
   Abre un fichero FLI para reproducirlo, leyendo los datos del disco o de
   la memoria respectivamente. Devuelve FLI_OK con xito. La informacin del
   FLI actual est almacenada en variables globales, por lo que slo puede
   tener una animacin abierta a la vez.

void close_fli();
   Cierra un FLI cuando haya acabado con l.

int next_fli_frame(int loop);
   Lee el siguiente cuadro de la animacin actual. Si loop est activado, el
   reproductor volver al principio cuando llegue al final del fichero, o
   devolver FLI_EOF si loop est desactivado. Devuelve FLI_OK con xito,
   FLI_ERROR o FLI_NOT_OPEN si hubo error, y FLI_EOF al alcanzar el final del
   fichero. El cuadro es ledo y almacenado en las variables globales
   fli_bitmap y fli_palette.

extern BITMAP *fli_bitmap;
   Contiene el cuadro actual de la animacin FLI/FLC.

extern PALETTE fli_palette;
   Contiene la paleta del FLI actual.

extern int fli_bmp_dirty_from;
extern int fli_bmp_dirty_to;
   Estas variables son fijadas por next_fli_frame() para indicar qu parte
   de fli_bitmap ha cambiado desde la ltima llamada a
   reset_fli_variables(). Si fli_bmp_dirty_from es mayor que
   fli_bmp_dirty_to, el bitmap no cambi. De otro modo, las lneas de
   fli_bmp_dirty_from a fli_bmp_dirty_to (inclusive) fueron alteradas.
   Puede usar estos valores cuando copie fli_bitmap en pantalla, para
   evitar mover datos innecesariamente.

extern int fli_pal_dirty_from;
extern int fli_pal_dirty_to;
   Estas variables son fijadas por next_fli_frame() para indicar qu parte
   de fli_palette fue cambiada desde la ltima llamada a
   reset_fli_variables(). Si fli_pal_dirty_from es mayor que
   fli_pal_dirty_to, la paleta no fue modificada. De otro modo, los colores
   de fli_pal_dirty_from a fli_pal_dirty_to (inclusive) fueron alterados.
   Puede usar estas variables cuando actualice la paleta hardware, para
   evitar llamadas innecesarias a set_palette().

void reset_fli_variables();
   Una vez haya hecho lo que fuese a hacer con fli_bitmap y fli_palette,
   llame esta funcin para resetear las variables fli_bmp_dirty_* y
   fli_pal_dirty_*.

extern int fli_frame;
   Variable global que contiene el nmero de cuadro actual del fichero FLI.
   Esto es til para sincronizar otros eventos con la animacin, por ejemplo
   podra comprobarla en la funcin callback de play_fli() y usarla para
   reproducir un sample en un punto particular.

extern volatile int fli_timer;
   Variable global para cronometrar la reproduccin FLI. Cuando abre un
   fichero FLI, una interrupcin de temporizador es instalada, la cual
   incrementa esta variable cada vez que se va a visualizar un nuevo cuadro.
   Llamando a next_fli_frame() la decrementa, por lo que puede comprobarla
   y saber el momento de ensear un nuevo cuadro cuando sea mayor que cero.



===============================================================
============ 22 Rutinas de inicializain de sonido ============
===============================================================

int detect_digi_driver(int driver_id);
   Detecta si el dispositivo especificado de sonido digital est disponible.
   Devuelve el mximo nmero de voces que el driver puede proporcionar, o
   cero si el hardware no est presente. Esta funcin debe llamarse _antes_
   de install_sound().

int detect_midi_driver(int driver_id);
   Detecta si el dispositivo especificado de sondo MIDI est disponible.
   Devuelve el nmero mximo de voces que el dirver puede proporcionar, o
   cero si el hardware no est presente. Hay dos valores especiales que
   pueden ser devueltos y que debera controlar: si la funcin devuelve -1
   se trata de un controlador ladrn de  notas (ej. DIGMID) que comparte las
   voces con el driver de sonido digital actual, y si devuelve 0xFFFF es un
   dispositivo externo como un MPU-401, en los cuales no hay manera de
   determinar cuantas voces hay disponibles. Esta funcin debe llamarse
   _antes_ de install_sound().

void reserve_voices(int digi_voices, int midi_voices);
   Llame esta funcin para especificar el nmero de voces que van a ser
   usadas por los controladores de sonido digital y MIDI respectivamente.
   Esto debe ser llamado _antes_ de llamar install_sound(). Si reserva
   demasiadas voces, las llamadas siguientes a install_sound() fallarn.
   Cuntas voces haya disponibles, depende del controlador, y en algunos
   casos llegar a reservar ms de las deseadas (ejemplo: los controladores
   de msica sinttica FM siempre dan 9 voces en una OPL2 y 18 en una OPL3,
   y el controlador de sonido digital de la SB redondear el nmero de voces
   al siguiente valor potencia de dos). Pase un valor negativo para
   recuperar los valores por defecto. Debera tener en cuenta, que la
   calidad del sonido es inversamente proporcional al nmero de voces que
   reserve, por lo que no reserve ms de las que necesite.

void set_volume_per_voice(int scale);
   Por defecto, cuando reserva ms voces para su driver de sonido digital,
   Allegro intentar reducir el volmen de cada una de ellas para
   compensarlo. Esto se hace para evitar la distorsin. Por defecto el
   volmen por voz es tal, que si reserva n voces, puede reproducir hasta
   n/2 sonidos normalizados centrados sin riesgo de distorsin. La excepcin
   es cuando tiene menos de 8 voces, ya que el volmen queda igual que para
   8 voces.

   Si el sonido resultante es demasiado alto o demasiado bajo, esta funcin
   puede ser usada para ajustar el volmen de cada voz. Primero debera
   verificar que sus altavoces estn ajustados a un volmen razonable, el
   volmen global de Allegro ajustado al mximo (mire set_volume() ms
   abajo), y cualquier otro tipo de mezcladores como el control de volmen
   de Windows estn ajustados razonablemente.

   Una vez haya determinado que el volmen de Allegro no es ideal para su
   aplicacin, use esta funcin para ajustarlo. Esto debe ser realizado
   _antes_ de llamara install_sound(). Note que esta funcin por ahora slo
   es relevante para los drivers que usan el mezclador de Allegro (la
   mayora de ellos).

   Si pasa un 0 a esta funcin, cada sonido centrado ser reproducido al
   mximo volmen posible sin distorsin, al igual que los sonidos
   reproducidos con un driver mono. Los sonidos en los extremos izquierdo y
   derecho sern distorsionados si se reproducen al mximo volmen. Si
   quiere reproducir sonidos panoramizados sin distorsin al mximo volmen,
   debe pasar 1 a esta funcin. Nota: esto es diferente del comportamiento
   que haba en las WIPs 3.9.34, 3.9.35 y 3.9.36. Si usa esta funcin con
   cualquiera de esas versiones, deber incrementar su parmetro en uno para
   obtener el mismo volmen.

   Cada vez que incremente el parmetro en uno, el volmen de cada voz ser
   reducido a la mitad. Por ejemplo, si pasa 4, podr reproducir hasta 16
   sonidos centrados con volmen mximo sin ninguna distorsin.

   Aqu estn los valores por defecto, dependiendo del nmero de voces:

      1-8 voces - set_volume_per_voice(2);
       16 voces - set_volume_per_voice(3);
       32 voces - set_volume_per_voice(4);
       64 voces - set_volume_per_voice(5);

   Por supuesto esta funcin no modificar el volmen que usted especifique
   mediante play_sample() o voice_set_volume(). Simplemente alterar la
   salida global del programa. Si reproduce sonidos a un volmen bajo, o
   si no estn nromalizados, podr reproducir ms sonidos simultneamente
   sin distorsin.

   Aviso: Allegro usa una tabla de recorte para recortar la onda de sonido.
   Esta tabla es lo suficientemente grande para acomodar un sonido total de
   hasta 4 veces el mximo posible sin distorsin. Si su volmen se sale de
   ste lmite, la onda 'dar la vuelta' (los picos sern valles y
   viceversa), distorsionando aun ms el sonido. Debe tener cuidado para que
   esto no ocurra.

   Es recomendado que introduzca el valor de este parmetro de forma fija en
   su programa en vez de ofrecerlo al usuario. El usuario puede alterar el
   volmen con el fichero de configuracin, o puede modificarlo con
   set_volume().

   Para restaurar el volmen por voz a su comportamiento habitual, pase -1.

int install_sound(int digi, int midi, const char *cfg_path);
   Inicializa el mdulo de sonido. Normalmente debera pasarle
   DIGI_AUTODETECT y MIDI_AUTODETECT como los parmetros de controlador, en
   cuyo caso Allegro leer la configuracin del hardware del fichero de
   configuracin actual. Esto permite al usuario seleccionar diferentes
   valores mediante una utilidad de setup: vea la seccin de configuracin
   para ver los detalles. Alternativamente, veal la documentacin especfica
   de la plataforma para tener una lista de los drivers disponibles. El
   parmetro cfg_path est presente slo por compatibilidad con las versiones
   anteriores de Allegro, y no tiene ningn efecto. Devuelve cero si el
   sonido se instal correctamente, y -1 si fall. Si falla guardar una
   descripcin del problema en allegro_error.

void remove_sound();
   Limpia el entorno cuando haya acabado con las rutinas de sonido.
   Normalmente no hace falta que llame esto, ya que allegro_exit() lo har
   por usted.

void set_volume(int digi_volume, int midi_volume);
   Altera el volumen de salida del sonido. Especifique el volumen para la
   reproduccin de MIDIs y samples digitales, con enteros de 0 a 255, o pase
   un valor negativo para no cambiar alguno de los ajustes. Es posible que
   esta rutina use el mezclador de hardware para controlar el volumen, de
   otro modo, le dir a los reproductores de samples y MIDI que simulen el
   mezclador por software.



=========================================================
============ 23 Rutinas de samples digitales ============
=========================================================

SAMPLE *load_sample(const char *filename);
   Carga un sample de un fichero, devolviendo un puntero a l, o NULL si hay
   error. Actualmente, esta funcin soporta ficheros WAV mono o estreo y
   ficheros VOC mono, tanto de 8 como 16 bits.

SAMPLE *load_wav(const char *filename);
   Carga un sample de un fichero RIFF WAV.

SAMPLE *load_voc(const char *filename);
   Carga un sample de un fichero VOC de Creative Labs.

SAMPLE *create_sample(int bits, int stereo, int freq, int len);
   Construye una nueva estructura de samples del tipo especificado. El campo
   data apunta a un bloque de datos de onda: lee la definicin de la
   estructura en allegro/digi.h para ms detalles.

void destroy_sample(SAMPLE *spl);
   Destruye una estructura de sample cuando no la necesita. Es seguro
   llamar esto incluso cuando el sample est siendo reproducido, porque lo
   comprueba y apaga si est activo.

void lock_sample(SAMPLE *spl);
   Bajo DOS, bloquea toda la memoria usada por el sample. Normalmente no
   necesita llamar a esta funcin porque load_sample() y create_sample() lo
   harn por usted.

int play_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);
   Reproduce un sample con el volumen, panoramizacin y frecuencia
   especificados. El volumen y panoramizacin van de 0 (min/izquierda) a 255
   (mx/derecha). La frecuencia no es absoluta, es relativa: 1000 representa
   la frecuencia a la que el sample fue grabado, 2000 es el doble, etc. Si
   la variable de repeticin est activada, el sample ser repetido hasta
   que llame stop_sample(), y puede ser manipulado mientras es reproducido
   llamando adjust_sample().

void adjust_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);
   Altera los parmetros de un sample mientras es reproducido (til para
   manipular sonidos con repeticin). Puede alterar el volumen, la
   panoramizacin y frecuencia, y tambin puede anular la variable de
   repeticin, lo que parar el sample cuando llegue al final del loop. Si
   hay varias copias del mismo sample activas, esto ajustar el primero que
   vaya a ser reproducido. Si el sample no est siendo reproducido, esto no
   tiene efecto.

void stop_sample(const SAMPLE *spl);
   Mata un sample, algo necesario si tiene uno en modo repeticin. Si hay
   varias copias del sample, todas sern paradas.

Si necesita controlar los samples con ms detalle, puede usar las funciones
de voz de bajo nivel en vez de llamar play_sample(). Esto conlleva ms
trabajo, porque debe reservar y liberar las voces explcitamente, ya que
stas no se liberan solas al acabar la reproduccin, pero esto le permite
especificar precisamente lo que quiere hacer con el sonido. Incluso puede
modificar algunos campos de la estructura sample:

   int priority;
      De 0 a 255 (por defecto 255), esto indica cmo las voces se reservan
      si intenta reproducir ms de las que controla el controlador. Esto
      puede ser usado para asegurarse de que los sonidos secundarios son
      recortados mientras que los importantes son reproducidos.

   unsigned long loop_start;
   unsigned long loop_end;
      Posiciones de repeticin en unidades de sample, por defecto ajustadas
      al comienzo y final del sample.

int allocate_voice(const SAMPLE *spl);
   Reserva una voz de la tarjeta y la prepara para reproducir el sample
   especificado, ajustando parmetros por defecto (volumen mximo,
   panoramizacin central, sin cambio de frecuencia, sin loop). Cuando acabe
   de usar la voz, debe liberarla llamando deallocate_voice() o
   release_voice(). Devuelve el nmero de voz, o -1 si no hay voces libres.

void deallocate_voice(int voice);
   Libera una voz de la tarjeta, parando su sonido y liberando los recursos
   que estuviese utilizando.

void reallocate_voice(int voice, const SAMPLE *spl);
   Ajusta una voz previamente reservada para usar un sample diferente.
   Llamar reallocate_voice(voice, sample) es equivalente a:

      deallocate_voice(voice);
      voice = allocate_voice(sample);

void release_voice(int voice);
   Libera una voz, indicando que ya no est interesado en su manipulacin.
   El sonido seguir siendo reproducido, y los recursos que usa sern
   liberados automticamente cuando acabe la reproduccin. Esto es
   esencialmente lo mismo que deallocate_voice(), pero espera a que los
   sonidos acaben para hacer efecto.

void voice_start(int voice);
   Activa una voz, usando los parmetros que le haya ajustado.

void voice_stop(int voice);
   Para una voz, almacenando la posicin actual y estado para que luego
   pueda continuar la reproduccin llamando voice_start().

void voice_set_priority(int voice, int priority);
   Ajusta la prioridad de una voz (rango 0-255). Esto es usado para decidir
   qu voces sern recortadas si intenta usar ms de las que puede soportar
   el controlador de la tarjeta de sonido.

SAMPLE *voice_check(int voice);
   Comprueba si una voz est activa, devolviendo el sample que est siendo
   reproducido, o NULL si la voz est inactiva (ej: la voz ha sido liberada,
   o ha llamado a release_voice() y el sample a terminado de ser
   reproducido).

int voice_get_position(int voice);
   Devuelve la posicin actual de la voz, en unidades de sample, o -1 si ha
   finalizado la reproduccin.

void voice_set_position(int voice, int position);
   Ajusta la posicin de una voz, en unidades de sample.

void voice_set_playmode(int voice, int playmode);
   Ajusta el estado de repeticin de una voz. Esto puede hacerse mientras se
   reproduce la voz, por lo que puede reproducir un sample con repeticin
   (teniendo el comienzo y final del loop ajustados correctamente), y
   entonces borrar la variable de repeticin cuando quiera finalizar el
   sonido, lo que har que ste llegue al final del loop, contine con la
   siguiente parte del sample, y acabe de modo normal. El parmetro mode es
   un campo de bits que contiene los siguientes valores.
   
   PLAYMODE_PLAY
      Reproduce el sample una sola vez. Esto est ajustado por defecto si no
      fija la variable de repeticin.
   
   PLAYMODE_LOOP
      Repite el sample, saltando al principio del bucle cuando se llegue al
      final de ste.
   
   PLAYMODE_FORWARD
      Reproduce el sample desde el comienzo hasta el final. Esto est
      ajustado por defecto si no activa el bit PLAYMODE_BACKWARD.
   
   PLAYMODE_BACKWARD
      Invierte la direccin del sample. Si combina esto con el bit de
      repeticin, el sample saltar al final del loop cuando llegue al
      comienzo (esto es: no necesita invertir los valores de comienzo y
      final del loop cuando reproduzca un sample en modo invertido).
   
   PLAYMODE_BIDIR
      Si se usa en combinacin con el bit loop, hace que el sample
      cambie de direccin cada vez que llega al extremo del bucle, por lo que
      alterna la direccin de reproduccin.
   
int voice_get_volume(int voice);
   Devuelve el volumen de la voz, en el rango 0-255.

void voice_set_volume(int voice, int volume);
   Ajusta el volumen de la voz, en el rango 0-255.

void voice_ramp_volume(int voice, int time, int endvol);
   Comienza un cambio de volumen (crescendo o diminuendo) desde el volumen
   actual al volumen final, especificando time en milisegundos.

void voice_stop_volumeramp(int voice);
   Interrumpe una operacin de cambio de volumen.

int voice_get_frequency(int voice);
   Devuelve la frecuencia actual en Hz.

void voice_set_frequency(int voice, int frequency);
   Ajusta la frecuencia de la voz en Hz.

void voice_sweep_frequency(int voice, int time, int endfreq);
   Comienza un cambio de frecuencia (glissando) desde la frecuencia actual
   hasta la frecuencia final, especificando time en milisegundos.

void voice_stop_frequency_sweep(int voice);
   Interrumpe una operacin de cambio de frecuencia.

int voice_get_pan(int voice);
   Devuelve la panoramizacin actual, desde 0 (izquierda) hasta 255
   (derecha).

void voice_set_pan(int voice, int pan);
   Ajusta la panoramizacin, desde 0 (izquierda) hasta 255 (derecho).

void voice_sweep_pan(int voice, int time, int endpan);
   Comienza una panoramizacin (movimiento izquierda <;->; derecha) desde la
   posicin actual hasta la posicin endpan, especificando time en
   milisegundos.

void voice_stop_pan_sweep(int voice);
   Interrumpe una panoramizacin.

void voice_set_echo(int voice, int strength, int delay);
   Ajusta el parmetro de eco para una voz (no implementado actualmente).

void voice_set_tremolo(int voice, int rate, int depth);
   Ajusta el parmetro de trmolo para una voz (no implementado
   actualmente).

void voice_set_vibrato(int voice, int rate, int depth);
   Ajusta el parmetro de vibrado para una voz (no implementado
   actualmente).



===================================================
============ 24 Rutinas de msica MIDI ============
===================================================

MIDI *load_midi(const char *filename);
   Carga un fichero MIDI (maneja ambos formatos 0 y 1), devolviendo un
   puntero a la estructura MIDI, o NULL si hubo problemas.

void destroy_midi(MIDI *midi);
   Destruye una estructura MIDI cuando ya no la necesite. Es seguro llamar
   esto incluso cuando el fichero MIDI est siendo reproducido, porque lo
   comprueba y detiene en caso de que est activo.

void lock_midi(MIDI *midi);
   Bajo DOS, bloquea toda la memoria usada por un fichero MIDI. Normalmente
   no necesita llamar a esta funcin porque load_midi() lo hace por usted.

int play_midi(MIDI *midi, int loop);
   Reproduce el fichero MIDI especificado, deteniendo cualquier msica
   anterior. Si la variable loop est activada, los datos sern repetidos
   hasta que los sustituya con otra cosa, de otro modo se parar la msica al
   final del fichero. Pasando un puntero NULL parar cualquier msica que
   est siendo reproducida. Devuelve distinto de cero si hubo problemas (esto
   puede ocurrir si un controlador wavetable cacheable no consigue cargar los
   samples requeridos, o al menos ocurrir en el futuro cuando alguien
   escriba algunos controladores wavetable cacheables :-)

int play_looped_midi(MIDI *midi, int loop_start, int loop_end);
   Reproduce un fichero MIDI con una posicin de bucle definida por el
   usuario. Cuando el reproductor llega al final del bucle o al final del
   fichero (loop_end puede ser -1 para repetir en EOF), volver al principio
   del comienzo del bucle. Ambas posiciones son especificadas en el mismo
   formato de golpes de ritmo que la variable midi_pos.

void stop_midi();
   Para la msica que est siendo reproducida. Esto es lo mismo que llamar
   play_midi(NULL, FALSE).

void midi_pause();
   Pone el reproductor MIDI en pausa.

void midi_resume();
   Continua la reproduccin de un MIDI pausado.

int midi_seek(int target);
   Avanza hasta la posicin especificada (midi_pos) en el fichero MIDI
   usado. Si el objetivo est antes en el fichero que el midi_pos actual,
   avanza desde el principio; de otro modo busca desde la posicin actual.
   Devuelve cero si no lo ha conseguido, no-cero si llega al final del
   fichero (1 significa que par la reproduccin, 2 significa que volvi a
   reproducir desde el principio). Si la funcin se para porque lleg a EOF,
   midi_pos contendr el valor negativo de la longitud del fichero MIDI.

void midi_out(unsigned char *data, int length);
   Introduce un bloque de comandos MIDI en el reproductor en tiempo real,
   permitindole activar notas, tocar campanas, etc, sobre el fichero MIDI
   que est siendo reproducido.

int load_midi_patches();
   Fuerza al controlador MIDI a cargar un conjunto de patches completo para
   ser usados. Normalmente no deber llamar esto, porque Allegro
   automticamente carga todos los datos requeridos por el fichero MIDI
   seleccionado, pero debe llamar esto antes de mandar mensajes de cambio de
   programa va comando midi_out(). Devuelve distinto de cero si ocurri un
   fallo.

extern volatile long midi_pos;
   Contiene la posicin actual (nmero de beat) del fichero MIDI, o un
   nmero negativo si no se est reproduciendo ninguna msica. Util para
   sincronizar animaciones con la msica, y para comprobar si un fichero MIDI
   se ha acabado de reproducir.

extern long midi_loop_start;
extern long midi_loop_end;
   Los puntos de comienzo y final del bucle, ajustados por la funcin
   play_looped_midi(). Estos pueden ser alterados mientras suena la msica,
   pero debera estar seguro de ponerlos a valores sensatos (comienzo <
   final). Si est cambiando ambos al mismo tiempo, asegrese de alterarlos
   en el mismo orden en caso de que una interrupcin midi ocurra entre sus
   dos cambios. Si los valores estn a -1, representan el comienzo y final
   del fichero respectivamente.

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);
   Funciones de enganche que permiten interceptar eventos MIDI del
   reproductor. Si se activan a cualquier cosa menos NULL, estas rutinas
   sern llamadas por cada mensaje MIDI, meta-evento, y bloque de datos
   exclusivo del sistema respectivamente. Estas funciones sern ejecutadas en
   un contexto de control de interrupcin, por lo que todo el cdigo y datos
   que usen debera estar bloqueado (locked), y no deben llamar funciones del
   sistema operativo. En general, simplemente use estas rutinas para activar
   algunas variables y responder a ellas ms tarde en su cdigo principal.

int load_ibk(char *filename, int drums);
   Lee una definicin de un fichero patch .IBK usado por el controlador
   Adlib. Si los tambores estn activados, lo cargar como un patch de
   percusin, de otro modo reemplazar el conjunto de instrumentos MIDI
   General. Puede llamar esto antes o despus de iniciar el cdigo de
   sonido, o simplemente puede activar las variables ibk_file e
   ibk_drum_file en el fichero de configuracin para cargar los datos
   automticamente. Fjese que esta funcin no tiene ningn efecto en
   otros controladores que no sean Adlib!



=======================================================
============ 25 Rutinas de flujo de sonido ============
=======================================================

Las rutinas de flujo de sonido son para reproducir sonidos digitales que son
demasiado grandes para caber en la estructura SAMPLE, bien porque son
ficheros enormes que quiere cargar en trozos segn necesita los datos, o
porque est haciendo algo inteligente como generar la onde del sonido en
tiempo real.

AUDIOSTREAM *play_audio_stream(int len, bits, stereo, freq, vol, pan);
   Esta funcin crea un nuevo flujo de audio y empieza a reproducirlo. El
   parmetro len es el tamao de cada bffer de transferencia (en samples),
   que normalmente debera ser una potencia de 2 y cercana a 1k: bffers
   ms grandes son ms eficientes y requieren menos actualizaciones, pero
   hay un desfase mayor entre los datos que usted porporciona y los que se
   estn reproduciendo actualmente. El parametro bits debe ser 8 o 16, freq
   es la frecuencia de muestreo de los datos, y los valores vol y pan usan
   el el mismo rango 0-255, como las funciones normales de reproduccin de
   samples. Si quiere ajustar la frecuencia, el volumen o la panoramizacin
   del flujo una vez se est reproduciendo, puede usar las funciones normales
   voice_*() con stream->;voice como un parmetro. Los datos del sample estan
   siempre en formato sin signo, con formas de onda en estreo que consisten
   en samples alternativos izquierda/derecha.

void stop_audio_stream(AUDIOSTREAM *stream);
   Destruye un flujo de audio cuando no lo necesite ms.

void *get_audio_stream_buffer(AUDIOSTREAM *stream);
   Debe llamar este funcin a intervalos regulares mientras el flujo de
   audio est siendo reproducido, para proveer el siguiente buffer de datos
   del sample (cuanto ms pequeo sea el tamao del buffer del flujo, ms
   frecuentemente debe llamar esta funcin). Si devuelve NULL, el flujo
   todava est reproduciendo los datos y no debe hacer nada. Si devuelve un
   valor, esa es la localizacin del prximo buffer a tocar, y debera
   cargar el nmero apropiado de samples (tantos como especific al crear
   el flujo) a esa direccin, por ejemplo usando un fread() de un fichero.
   Despus de llenar el buffer con datos, llame free_audio_stream_buffer()
   para indicar que los datos nuevos ahora son vlidos. Fjese que esta
   funcin no debera ser llamada desde una funcin de temporizador.

void free_audio_stream_buffer(AUDIOSTREAM *stream);
   Llame esta funcin despus de que get_audio_stream_buffer() devuelva una
   direccin que no sea NULL, para indicar que ya ha cargado un nuevo bloque
   de samples en esa direccin y que los datos estn listos para ser
   reproducidos.



===========================================================
============ 26 Rutinas de grabacin de sonido ============
===========================================================

int install_sound_input(int digi_card, int midi_card);
   Inicializa el mdulo de grabacin de sonido, devolviendo cero si no hubo
   problemas. Debe instalar el sistema normal de reproduccin de sonido
   antes de llamar esta rutina. Los dos parmetros de tarjetas deben ser los
   mismos que en install_sound(), incluyendo DIGI_NONE y MIDI_NONE para
   desactivar partes del mdulo, o DIGI_AUTODETECT y MIDI_AUTODETECT para
   adivinar el hardware.

void remove_sound_input();
   Desactiva el mdulo cuando haya acabado de usarlo. Normalmente no debe
   llamar esta funcin, porque remove_sound() y/o allegro_exit() lo harn
   por usted.

int get_sound_input_cap_bits();
   Comprueba qu formatos de sonido son soportados por el controlador de
   entrada de audio, devolviendo uno de los valores del campo de bits:

      0 = entrada de audio no soportada
      8 = entrada de audio de ocho bits soportada
      16 = entrada de audio de diecisis bits soportada
      24 = entrada de audio de ocho y diecisis bits soportada

int get_sound_input_cap_stereo();
   Comprueba si el controlador de entrada de audio actual es capaz de grabar
   en estreo.

int get_sound_input_cap_rate(int bits, int stereo);
   Devuelve la frecuencia de grabacin de samples mxima posible en el
   formato especificado, o cero si los ajustes no son soportados.

int get_sound_input_cap_parm(int rate, int bits, int stereo);
   Comprueba si la frecuencia de grabacin especificada, nmero de bits y
   mono/estreo es soportado por el controlador de audio actual, devolviendo
   uno de los siguientes valores:

      0 = es imposible grabar en este formato
      1 = grabar es posible, pero la salida de audio ser suspendida
      2 = es posible grabar y reproducir sonidos a la vez
      -n = razn de muestreo no soportada, pero la razn 'n' puede funcionar

int set_sound_input_source(int source);
   Selecciona la fuente de la entrada de audio, devolviendo cero si no hubo
   problemas o -1 si el hardware no proporciona un registro de seleccin de
   entrada. El parmetro debe ser uno de los valores:

      SOUND_INPUT_MIC
      SOUND_INPUT_LINE
      SOUND_INPUT_CD

int start_sound_input(int rate, int bits, int stereo);
   Comienza a grabar en el formato especificado, suspendiendo la
   reproduccin de sonidos si es necesario (esto suceder siempre con los
   controladores actuales). Devuelve el tamao del buffer en bytes si hubo
   xito, o cero si hubo algn error.

void stop_sound_input();
   Para la grabacin, ajustando la tarjeta de vuelta al modo normal de
   reproduccin.

int read_sound_input(void *buffer);
   Recupera el buffer de audio grabado ms reciente en el lugar
   especificado, devolviendo no-cero si el buffer ha sido copiado, o cero si
   todava no hay nuevos datos disponibles. El tamao del buffer puede ser
   obtenido comprobando el valor de retorno de start_sound_input(). Debe
   llamar esta funcin a intervalos regulares durante la grabacin
   (tpicamente unas 100 veces por segundo), o podra perder datos. Si no
   puede hacer esto lo suficientemente rpido, use la funcin callback
   digi_recorder() para almacenar la onda de sonido en un buffer ms grande
   que haya creado antes. Nota: muchas tarjetas de sonido reproducen un
   click o sonido raro cuando alternan entre los modos de grabacin y
   reproduccin, por lo que es buena idea descartar el primer buffer despus
   de comenzar la grabacin. La onda siempre se almacena en formato sin
   signo, con los datos estreo siendo samples alternados izquierda/derecha.

extern void (*digi_recorder)();
   Si est activada, esta funcin es llamada por el controlador de entrada
   de sonido siempre que un nuevo buffer de sonido est disponible, momento
   en el que puede usar read_sound_input() para copiar los datos a un lugar
   permanente. Esta rutina se ejecuta en contexto de interrupcin, por lo
   que debe ejecutarse muy rpidamente, el cdigo y la memoria que modifica
   debe estar bloqueada (locked), y no puede llamar desde ella rutinas de
   sistema o acceder a ficheros del disco.

extern void (*midi_recorder)(unsigned char data);
   Si est activada, esta funcin es llamada por el controlador de entrada
   MIDI siempre que un nuevo byte de datos MIDI est disponible. Se ejecuta
   en contexto de interrupcin, por lo que debe ser muy rpida y su
   cdigo/datos deben estar bloqueados (locked).



=============================================================
============ 27 Rutinas de ficheros y compresin ============
=============================================================

Las siguientes rutinas implementan un sistema de ficheros I/O con buffer
rpido, que soporta la lectura y escritura de ficheros comprimidos usando un
algoritmo de buffer de anillo basado en el compresor LZSS de Haruhiko
Okumura. Esto no consigue tan buenas compresiones como zip o lha, pero la
descompresin es muy rpida y no requiere mucha memoria. Los ficheros
comprimidos siempre comienzan con el valor de 32 bits F_PACK_MAGIC, y
autodetecta ficheros con el valor F_NOPACK_MAGIC.

Los siguients bit FA_* estn garantizados en todas las plataformas:
FA_RDONLY, FA_HIDDEN, FA_SYSTEM, FA_LABEL, FA_DIREC y FA_ARCH. No use otros
bits de DOS/Windows, o su cdigo no compilar en otras plataformas. Los bits
FA_SYSTEM, FA_LABEL y FA_ARCH slo son tiles bajo DOS/Windows (entradas con
el bit de sistema, archivo y etiquetas de volmen). FA_RDONLY es para
directorios con el bit de slo lectura en sistemas tipo DOS, o directorios
sin permiso de escritura por el usuario actual en sistemas tipo Unix.
FA_HIDDEN es para ficheros ocultos en DOS, o aquellos que compeinzan con '.'
en sistemas Unix (excepto los ficheros '.' y '..'). FA_DIREC representa
directorios. Los bits se pueden combinar usando '|' (operador OR binario).

Cuando estos bits son pasados a las funciones como el parmetro 'attrib',
representan un superconjunto de los bits que debe tener un fichero para ser
includo en la bsqueda. Esto es, para que un fichero encaje con el patrn,
sus atributos pueden contener cualquiera de los bits especificados, pero no
debe contener ningno de los bits no especificados. Por lo tanto, si usa
'FA_DIREC | FA_RDONLY', los ficheros y directorios normales sern includos
junto con los ficheros y directorios de slo lectura, pero no los ficheros y
directorios ocultos. Similarmente, si usa 'FA_ARCH' entonces tanto los
ficheros archivados como no archivados sern includos.

void get_executable_name(char *buf, int size);
   Llena buf con la ruta completa del ejecutable actual, escribiendo como
   mucho size bytes. Esto normalmente viene de argv[0], pero en los sistemas
   Unix donde argv[0] no especifica la ruta, se buscar el fichero en $PATH.

char *fix_filename_case(char *path);
   Convierte un nombre de fichero a un estado estandarizado. En platadormas
   DOS, los nombres sern todo maysculas. Devuelve una copia del parmetro
   de camino.

char *fix_filename_slashes(char *path);
   Convierte los separadores de directorios de un nombre de fichero a un
   carcter estndar. En plataformas DOS, esto es la antibarra. Devuelve una
   copia del parmetro de camino.

char *fix_filename_path(char *dest, const char *path, int size);
   Convierte un nombre de fichero parcial en una ruta completa, escribiendo
   en dest como mximo el nmero de bytes especificados. Devuelve una copia
   del parmetro dest.

char *replace_filename(char *dest, const char *path,
         const char *filename, int size);
   Sustituye el camino+nombre de fichero especificados con un nuevo nombre
   de fichero, escribiendo en dest como mximo el nmero de bytes
   especificados. Devuelve una copia del parmetro dest.

char *replace_extension(char *dest, const char *filename,
          const char *ext, int size);
   Sustituye el nombre de fichero+extensin especificados con una nueva
   extensin, escribiendo en dest como mximo el nmero de bytes
   especificados. Devuelve una copia del parmetro dest.

char *append_filename(char *dest, const char *path,
        const char *filename, int size);
   Concatena el nombre de fichero especificado al final del camino
   especificado, escribiendo en dest como mximo el nmero de bytes
   especificados. Devuelve una copia del parmetro dest.

char *get_filename(const char *path);
   Cuando se le pasa el path especfico de un fichero, devuelve un puntero a
   la porcin del nombre del fichero. Tanto '\' como '/' son reconocidos
   como separadores de directorios.

char *get_extension(const char *filename);
   Cuando se le pasa un nombre de fichero completo (con o sin informacin
   de path) devuelve un puntero a la extensin del fichero.

void put_backslash(char *filename);
   Si el ltimo caracter de un nombre no es '\', '/', '#' o un separador de
   dispositivo (ej: ':' bajo DOS), esta rutina concatenar un '\' o '/'
   (dependiendo de la plataforma). Nota: ignore el nombre de la funcin, est
   anticuado.

int file_exists(const char *filename, int attrib, int *aret);
   Chequea la existencia de un fichero de nombre y atributos dados (lea ms
   arriba), devolviendo distinto de cero si el fichero existe. Si aret no es
   NULL, contendr los atributos del fichero existente al acabar la llamada.
   Si ocurre un error, el cdigo de error de sistema ser almacenado en
   errno.

int exists(const char *filename);
   Versin reducida de file_exists(), que comprueba la existencia de ficheros
   normales, los cuales pueden tener los bits de archivo o slo lectura
   activados, pero no son ocultos, directorios, ficheros de sistema, etc.

long file_size(const char *filename);
   Devuelve el tamao del fichero en bytes. Si el fichero no existe u ocurre
   un error, devolver cero y almacenar el cdigo de error de sistema en
   errno.

time_t file_time(const char *filename);
   Devuelve el tiempo de modificacin de un fichero (nmero de segundos desde
   las 00:00:00 GMT del 1 de Enero de 1970).

int delete_file(const char *filename);
   Borra un fichero.

int for_each_file(const char *name, int attrib,
                  void (*callback)(const char *filename, int attrib,
                  int param), int param);
   Encuentra todos los ficheros que se ajusten a la mscara (ej: *.exe) y
   atributos especificados (lea ms arriba), y ejecuta callback() por cada
   uno de ellos. A callback() se le pasan tres parmetros, el primero es la
   cadena que contiene el nombre completo del fichero, el segundo los
   atributos del fichero, y el tercer parmetro es un entero que es copia de
   param (puede usar esto para lo que quiera). Si ocurre un error, el cdigo
   de error ser almacenado en errno, y callback() puede abortar
   for_each_file al activar errno. Devuelve el nmero de llamadas con xito
   hechas a callback().

int al_findfirst(const char *pattern, struct al_ffblk *info, int attrib);
   Funcin de bajo nivel para buscar ficheros. Esta funcin busca el primer
   fichero que concuerde con el patrn y los atributos de fichero
   especificados (lea ms arriba). La informacin sobre el fichero (si
   existe) ser puesta en la estructura al_ffblk que debe proveer usted. La
   funcin devuelve cero si se encontr un fichero, distinto de cero si no se
   encontr ninguno, y en este caso ajusta errno apropiadamente. La
   estructura al_ffblk tiene la siguiente forma:

     struct al_ffblk
     {
         int attrib;       - atributos del fichero encontrado
         time_t time;      - tiempo de modificacin del fichero
         long size;        - tamao del fichero
         char name[512];   - nombre del fichero
     };

   Hay ms cosas en esta estructura, pero son para uso interno.

int al_findnext(struct al_ffblk *info);
   Esto encuentra el siguiente fichero en una bsqueda comenzada por
   al_findfirst. Devuelve cero si se encontr un fichero, distinto de cero si
   no se encontr ninguno, y en ste caso ajusta errno apropiadamente.

void al_findclose(struct al_ffblk *info);
   Esto cierra una bsqueda previamente abierta mediante al_findfirst().
   
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);
   Busca un archivo de recursos, ej allegro.cfg o language.dat. Pasndole
   una cadena resource describiendo qu se est buscando, junto con una
   informacin extra opcional como la extensin por defecto, en qu datafile
   mirar, qu nombre de objeto debera tener en el datafile, cualquier
   variable de entorno que se tenga que chequear, y cualquier subdirectorio
   que le gustara comprobar, as como la localizacin por defecto, esta
   funcin mira en un infierno de sitios distintos :-) Devuelve cero si
   ha tenido xito, y guarda el path absoluto del fichero (como mucho size
   bytes) en el parmetro dest.

void packfile_password(const char *password);
   Activa el password de encriptacin que ser usado para todas las
   operaciones de lectura/escritura con ficheros abiertos en el futuro con
   las funciones packfile de Allegro (estn comprimidos o n), incluyendo las
   rutinas de configuracin, salvado y cargado. Los ficheros escritos con un
   password no pueden ser ledos a no ser que se seleccione el password
   correcto, por lo que cuidado: si olvida la clave, nadie podr recuperar
   su datos! Pase NULL o una cadena vaca para volver al modo normal, no
   encriptado. Si est usando esta funcin para evitar que otros accedan a
   sus ficheros de datos, tenga cuidado de no salvar una copia obvia de su
   clave en el ejecutable: si hay cadenas como "Soy la clave del fichero de
   datos", sera muy fcil acceder a sus datos :-)

   Importante: tan pronto como haya abierto un fichero usando un password de
   encriptacin, llame a packfile_password(NULL). Mejor an, no use esta
   funcin. Nunca.

PACKFILE *pack_fopen(const char *filename, const char *mode);
   Abre un fichero segn el modo, que puede contener cualquiera de los
   siguientes letras.

      'r' - abrir fichero para leer.

      'w' - abrir fichero para escribir, sobreescribiendo datos existentes.

      'p' - abrir fichero en modo comprimido. Los datos sern comprimidos a
       medida que se escriben en el fichero, y automticamente
       descomprimidos durante las operaciones de lectura. Los ficheros
       creados de este modo producirn basura si se intentan leer sin
       activar antes este modo.

      '!' - abrir fichero para escribir en modo normal, sin compresin, pero
       aade el valor F_NOPACK_MAGIC al comienzo del fichero, para que luego
       pueda ser abierto en modo comprimido y Allegro autodetectar que los
       datos no necesitan ser descomprimidos.

   En vez de estos modos, una de las constantes F_READ, FWRITE,
   F_READ_PACKED, F_WRITE_PACKED o F_WRITE_NOPACK puede ser usada como el
   parmetro de modo. Si todo funciona, pack_fopen() devuelve un puntero a
   una estructura de fichero, y con error, devuelve NULL y almacena el
   cdigo de error en errno. Un intento de leer un fichero normal en modo
   comprimido activar errno a EDOM.

   Las funciones de ficheros tambin entienden varios nombres "mgicos" que
   pueden ser usados por varios motivos. Estos nombres son:

      "#" - lee datos que han sido aadidos al fichero ejecutable con la
      utilidad exedat, como si fuesen de un fichero independiente.

      'nombre.dat#nombre_obj' - abre un objeto especfico de un fichero de
      datos, y lo lee como si fuese de un fichero normal. Puede crear
      ficheros de datos anidados exctamente como una estructura normal de
      directorios, por ejemplo podra abrir el fichero
      'nombre.dat#graficos/nivel1/datomapa'.

      '#nombre_obj' - combinacin de lo de arriba, leer un objeto de un
      fichero de datos que ha sido aadido al ejecutable.

   Con estos nombres especiales, los contenidos de un objeto de un fichero de
   datos o de un fichero aadido pueden ser ledos de modo idntico que un
   fichero normal, por lo que cualquiera de las funciones de acceso a
   ficheros de Allegro (ejemplo: load_pcx() y set_config_file()) pueden ser
   usadas para leerlos. Sin embargo, no podr escribir en estos ficheros:
   slo pueden ser ledos. Adems, debe tener su fichero de datos
   descomprimido o con compresin por objetos si planea leer objetos
   individuales (de otra manera, habr una sobrecarga de bsqueda al ser
   ledo). Finalmente, tenga en cuenta que los tipos de objetos especiales de
   Allegro no son los mismos que los de los ficheros de los que importe los
   datos. Cuando importe datos como bitmaps o samples en el grabber, stos
   son convertidos a un formato especfico de Allegro, pero el marcador de
   sintaxis de ficheros '#' lee los objetos como trozos binarios raw. Esto
   significa, que si por ejemplo, quiere usar load_pcx para leer una imagen
   de un fichero de datos, debera importarla como un bloque binario en vez
   de un objeto BITMAP.

int  pack_fclose(PACKFILE *f);
int  pack_fseek(PACKFILE *f, int offset);
int  pack_feof(PACKFILE *f);
int  pack_ferror(PACKFILE *f);
int  pack_getc(PACKFILE *f);
int  pack_putc(int c, PACKFILE *f);
int  pack_igetw(PACKFILE *f);
long pack_igetl(PACKFILE *f);
int  pack_iputw(int w, PACKFILE *f);
long pack_iputl(long l, PACKFILE *f);
int  pack_mgetw(PACKFILE *f);
long pack_mgetl(PACKFILE *f);
int  pack_mputw(int w, PACKFILE *f);
long pack_mputl(long l, PACKFILE *f);
long pack_fread(void *p, long n, PACKFILE *f);
long pack_fwrite(const void *p, long n, PACKFILE *f);
char *pack_fgets(char *p, int max, PACKFILE *f);
int  pack_fputs(const char *p, PACKFILE *f);

   Todas estas funcionan como las funciones equivalentes stdio, excepto que
   pack_fread() y pack_fwrite() toman un slo parmetro de tamao en vez de
   ese estpido sistema de tamao y num_elements, slo puede avanzar en un
   fichero hacia delante desde la posicin relativa actual, y pack_fgets() no
   incluye el retorno de carro en las cadenas que devuelve. Las rutinas
   pack_i* y pack_m leen y escriben valores de 16 y 32 bits usando los
   sistemas de orden de Intel y Motorola respectivamente. Tome nota que la
   bsqueda es muy lenta cuando lea ficheros comprimidos, y que debera ser
   evitada a no ser que sepa que el fichero no est comprimido.

PACKFILE *pack_fopen_chunk(PACKFILE *f, int pack);
   Abre sub-chunks en un fichero. Los chunks son primariamente usados por el
   cdigo de ficheros de datos, pero pueden serle tiles para sus propias
   rutinas de ficheros. Un chunk provee una vista lgica de parte de un
   fichero, que puede ser comprimido como un ente individual y ser
   automticamente insertado y comprobar los contadores de tamao para
   prevenir la lectura despus del final del chunk. Para escribir un chunk
   en un fichero f, use este cdigo:

      /* Asumo que f es un PACKFILE * que ha sido abierto en modo escritura*/
      f = pack_fopen_chunk(f, pack);
      escribe datos en f
      f = pack_fclose_chunk(f);

   Los datos escritos en el chunk sern precedidos con dos contadores de
   tamao (32 bits, big-endian). Para los chunks sin compresin, stos sern
   ajustados al tamao de los datos del chunk. Para chunks comprimidos
   (creados al activar la variable pack), el primer tamao es el tamao real
   del chunk, y el segundo ser el tamao negativo de los datos
   descomprimidos.

   Para leer el chunk, use este cdigo:

      /* Asumo que f es un PACKFILE * que ha sido abierto en modo escritura*/
      f = pack_fopen_chunk(f, FALSE);
      lee datos de f
      f = pack_fclose_chunk(f);

   Esta secuencia leer los contadores de tamao creados cuando el chunk fue
   escrito, y automticamente descomprimir el contenido del chunk si fue
   comprimido. El tamao tambin evitar leer despus del final del chunk
   (Allegro devolver EOF si intenta esto), y automticamente ignora los
   datos no ledos del chunk cuando llamae pack_fclose_chunk().

   Los chunks pueden ser anidados unos dentro de otros al hacer llamadas
   repetidas a pack_fopen_chunk(). Al escribir un fichero, el estado de
   compresin es heredado del fichero padre, por lo que slo tiene que
   activar la variable pack si el fichero padre no fue comprimido pero
   quiere comprimir los datos del chunk. Si el fichero padre ya est
   abierto en modo comprimido, activar la variable pack har que los datos
   sean comprimidos dos veces: una cuando los datos son escritos en el
   chunk, y otra cuando el chunk es escrito en el fichero padre.

PACKFILE *pack_fclose_chunk(PACKFILE *f);
   Cierra un sub-chunk de un fichero, que previamente ha sido obtenido al
   llamar pack_fopen_chunk().



=========================================================
============ 28 Rutinas de ficheros de datos ============
=========================================================

Los ficheros de datos son creados por la utilidad grabber, y tienen la
extensin .dat. Pueden contener bitmaps, paletas de color, fuentes, sonidos,
msica MIDI, animaciones FLI/FLC y cualquier otro tipo binario de datos que
importe.

Atencin: cuando use imgenes truecolor, debera activar el modo grfico
antes de cargar ningn bitmap! Si no, el formato (RGB o BGR) ser
desconocido, y el fichero probablemente ser convertido errneamente.

Mire la documentacin en pack_fopen() para obtener informacin sobre como
leer directamente de un fichero de datos.

DATAFILE *load_datafile(const char *filename);
   Carga un fichero de datos en memora, devolviendo un puntero hacia l, o
   NULL si ha habido un error. Si el fichero de datos ha sido encriptado,
   primero tiene que usar la funcin packfile_password() para introducir la
   clave correcta. Mire grabber.txt para mas informacin. Si el fichero de
   datos contiene grficos truecolor, debe entrar en modo grfico o llamar
   set_color_conversion() antes de cargarlo.

DATAFILE *load_datafile_callback(const char *filename,
                                 void (*callback)(DATAFILE *d));
   Carga el datafile en memoria, llamando a la funcin de enganche (hook)
   especificada una vez por cada objeto en el fichero, pasndole un puntero
   al objeto ledo recientemente.

void unload_datafile(DATAFILE *dat);
   Libera todos los objetos de un fichero de datos.

DATAFILE *load_datafile_object(const char *filename,
            const char *objectname);
   Carga un objeto especfico de un fichero dat. Esto no funcionar si
   elimina los nombres de los objetos del fichero, y ser muy lento si salva
   el fichero de datos con compresin general. Mire grabber.txt para ms
   informacin.

void unload_datafile_object(DATAFILE *dat);
   Libera un objeto previamente cargado con load_datafile_object().

DATAFILE *find_datafile_object(DATAFILE *dat, const char *objectname);
   Busca en un fichero de datos que est cargado un objeto con el nombre
   especificado, devolviendo un puntero a l, o NULL si el objeto no fue
   encontrado. Entiende '/' y '#' como separadores para paths de ficheros de
   datos anidados.

char *get_datafile_property(DATAFILE *dat, int type);
   Retorna la propiedad especifica de un objeto, o una cadena vaca si la
   propiedad no esta presente. Mire grabber.txt para mas informacin.

void register_datafile_object(int id, void *(*load)(PACKFILE *f, long size),
                                      void (*destroy)(void *data));
   Usado para aadir tipos de objetos propios, especificando las funciones
   de carga y destruccin de este tipo. Mire grabber.txt para mas
   informacin.

void fixup_datafile(DATAFILE *data);
   Si est usando ficheros de datos compilados (producidos por la utilidad
   dat2s) que contienen imgenes truecolor, tiene que llamar esta funcin
   una vez haya puesto el modo de vdeo que vaya a usar, para convertir
   los valores de los colores al formato apropiado. Puede intercambiar los
   formatos RGB y BGR, y convertirlos a diferentes profundidades de color
   siempre que sea posible sin cambiar el tamao de la imagen (por ejemplo:
   cambiando entre 15 y 16 bits de color para bitmaps y sprites RLE, y entre
   24 y 32 bits de color para sprites RLE).

Cuando cargue un fichero de datos, obtendr un puntero a un array de
estructuras DATAFILE:

   typedef struct DATAFILE
   {
      void *dat;     - puntero a los datos
      int type;      - tipo del dato
      long size;     - tamao de los datos en bytes
      void *prop;    - propiedades de los objetos
   } DATAFILE;

El campo type puede tener uno de los siguientes valores:

   DAT_FILE       - dat apunta a un fichero de datos anidado
   DAT_DATA       - dat apunta a un bloque ordinario de datos
   DAT_FONT       - dat apunta a una fuente
   DAT_SAMPLE     - dat apunta a un fichero de sonido
   DAT_MIDI       - dat apunta a un fichero MIDI
   DAT_PATCH      - dat apunta a un 'patch' para la GUS
   DAT_FLI        - dat apunta a una animacin FLI/FLC
   DAT_BITMAP     - dat apunta a una estructura BITMAP
   DAT_RLE_SPRITE - dat apunta a una estructura RLE_SPRITE
   DAT_C_SPRITE   - dat apunta a un sprite compilado linearmente
   DAT_XC_SPRITE  - dat apunta a un sprite de modo-X
   DAT_PALETTE    - dat apunta a un array de 256 estructuras RGB
   DAT_END        - bit especial que marca el final de una lista de datos

El programa grabber tambin puede producir un fichero de cabecera que define
el ndice de los objetos dentro de un fichero de datos como una serie de
constantes definidas, usando los nombres que les dio en el grabber. Por
ejemplo, si cre un fichero de datos llamado foo.dat que contiene el bitmap
llamado LA_IMAGEN, puede ensearlo con el siguiente fragmento de cdigo:

   #include "foo.h"

   DATAFILE *data = load_datafile("foo.dat");
   draw_sprite(screen, data[LA_IMAGEN].dat, x, y);

Si est programando en C++. obtendr un error porque el campo dat es un
puntero void y draw_sprite espera un puntero BITMAP. Puede solucionarlo con
una conversin de puntero. Ejemplo:

   draw_sprite(screen, (BITMAP *)data[LA_IMAGEN].dat, x, y);

Cuando carge un slo objeto de un fichero de datos, obtendr un puntero a
una estructura DATAFILE nica. Esto significa que no puede acceder a l como
un array, y no contiene el objeto DAT_END. Ejemplo:

   objeto_musica = load_datafile_object("datos.dat", "MUSICA");
   play_midi(objeto_musica->;dat);




==============================================================
============ 29 Rutinas matemticas de punto fijo ============
==============================================================

Allegro trae algunas rutinas para trabajar con nmeros de punto fijo, y
define el tipo 'fixed' como un entero de 32 bits con signo. La parte alta es
usada por el valor del entero y la parte baja es usada por el valor de la
fraccin, dando un rango de valores de -32768 a 32767 y un detalle de unos 4
o 5 decimales. Los nmeros de punto fijo pueden ser asignados, comparados,
aadidos, substrados, negados y desplazados (para multiplicar o dividir por
potencias de 2) usando los operadores de enteros normales, pero tendra que
tener cuidado de usar las rutinas de conversin apropiadas cuando combine
nmeros de punto fijo con enteros o nmeros de coma flotante. Escribir
'punto_fijo_1 + punto_fijo_2' esta bien, pero 'punto_fijo + entero' no esta
bien.

fixed itofix(int x);
   Convierte un valor de entero a punto fijo. Esto es lo mismo que x<<16.

int fixtoi(fixed x);
   Convierte un valor de punto fijo a entero, redondeando.
   
int fixfloor(fixed x);
   Devuelve el mayor entero menor que x. Esto es, redondea hacia el infinito
   negativo.

int fixceil(fixed x);
   Devuelve el menor intero mayor que x. Esto es, redondea hacia el infinito
   positivo.

fixed ftofix(float x);
   Convierte un valor de coma flotante a punto fijo.

float fixtof(fixed x);
   Convierte un valor de punto fijo a coma flotante.

fixed fixmul(fixed x, fixed y);
   Un valor de punto fijo puede ser multiplicado o dividido por un entero
   con los operadores normales '*' y '/'. Sin embargo, para multiplicar dos
   valores de punto fijo necesita usar esta funcin.

   Si hay desbordamiento o divisin por cero, errno ser activado y el valor
   mximo posible ser devuelto, pero errno no es limpiado si la operacin
   es realizada con xito. Esto significa que si va a comprobar un
   desbordamiento de divisin, debera poner errno=0 antes de llamar a
   fixmul().

fixed fixdiv(fixed x, fixed y);
   Divisin de valores de punto fijo: mire fixmul().

fixed fixadd(fixed x, fixed y);
   A pesar de que los nmeros de punto fijo pueden ser aadidos con el
   operador normal de enteros '+', eso no le da proteccin contra
   desbordamientos. Si el desbordamiento es un problema, debera usar esta
   funcin. Es mas lenta que los operadores de enteros, pero si hay un
   desbordamiento de divisin, ajustar el tamao del resultado en vez de
   dejarlo al azar, y activara errno.

fixed fixsub(fixed x, fixed y);
   Resta de nmeros en punto fijo: mire fixadd().

Las funciones de raz cuadrada, seno, coseno, tangente, cosecante y secante
estn implementadas usando tablas precalculadas, que son muy rpidas pero no
muy exactas. Por ahora, la cotangente realiza una bsqueda iterativa en la
tabla de la tangente, por lo que es mas lenta que las otras.

Los ngulos estn representados en formato binario con 256 siendo igual al
crculo completo, 64 es un ngulo recto y as sucesivamente. Esto tiene
la ventaja de que un 'and' a nivel de bits puede ser usado para que el
ngulo quede entre cero y el crculo completo, eliminando esos tests
cansinos 'if (angle >= 360)'.

fixed fixsin(fixed x);
   Mira la tabla precalculada del seno.

fixed fixcos(fixed x);
   Mira la tabla precalculada del coseno.

fixed fixtan(fixed x);
   Mira la tabla precalculada de la tangente.

fixed fixasin(fixed x);
   Mira la tabla de la cosecante.

fixed fixacos(fixed x);
   Mira la tabla de la secante.

fixed fixatan(fixed x);
   Cotangente de punto fijo.

fixed fixatan2(fixed y, fixed x);
   Versin de punto fijo de la rutina atan2() de libc.

fixed fixsqrt(fixed x);
   Raz cuadrada de punto fijo.

fixed fixhypot(fixed x, fixed y);
   Hypotenusa en punto fijo (devuelve la raz cuadrada de x*x + y*y).


Si est programando en C++ puede ignorar todo lo de arriba y usar la clase
"fija", que sobrecarga muchos operadores para proveer conversin automtica
desde y hacia valores enteros y de coma flotante, y llama las rutinas de
arriba cuando se necesitan. Sin embargo no debera mezclar la clase "fija"
con los typedefs de punto fijo, ya que el compilador tratar los valores de
punto fijo como enteros regulares e insertar conversiones innecesarias. Por
ejemplo, si x es un objeto de clase fija, llamar fixsqrt(x) devolver un
resultado errneo. Debera usar sqrt(x) o x.swrt() en vez de eso.


Las rutinas de punto fijo antes eran nombradas con el prefijo "f" en lugar
de "fix", ej: fixsqrt() antes era fsqrt(), pero tuvieron que ser renombradas
por conflictos con algunas implementaciones de la libc. Esto no debera
afectar a la mayora del cdigo existente dado que existen alias de
compatibilidad hacia atrs. Estos alias son funciones estticas inline que
enlazan los nombres antiguos con los nuevos, ej: fsqrt() llama a fixsqrt().
Puede desactivar estos alias definiendo la macro de preprocesador
ALLEGRO_NO_FIX_ALIASES antes de inclur allegro.h.



===================================================
============ 30 Rutinas matemticas 3D ============
===================================================

Allegro tambin contiene algunas funciones de ayuda de 3d para manipular
vectores, construir o usar matrices de transformacin, y hacer proyecciones
de perspectiva de un espacio 3d en la pantalla. Estas funciones no son, y
nunca sern, una librera 3d total (mi objetivo es dar rutinas de soporte
genricas, y no cdigo grfico muy especializado :-) pero estas funciones
pueden serle tiles para desarrollar su propio cdigo 3d.

Allegro usa el sistema de coordenadas de mano derecha, es decir, si apunta
con el dedo gordo de su mano derecha al eje positivo x, y con el ndice al
eje positivo y, su dedo corazn apuntar en la direccin positiva del eje z.
Esto tambin significa que para las rotaciones, si hace que el dedo gordo
de su mano derecha siga el eje de rotacin, sus dedos se curvarn en la
direccin positiva de la rotacin.

Hay dos versiones de todas las funciones matemticas de 3d: una usando
aritmtica de punto fijo, y la otra usando coma flotante. La sintaxis para
ambas es idntica, pero las funciones y estructuras de coma flotante tienen
el sufijo '_f'. Ejemplo: la funcin cross_product() de punto fijo tiene el
equivalente de coma flotante en cross_product_f(). Si est programando en
C++, Allegro tambin sobrecarga estas funciones para que las use con la
clase "fija".

La transformacin 3d se realiza modelando una matriz. Esta es un array de
4x4 nmeros que pueden ser multiplicados con un punto 3d para producir otro
punto 3d. Si ponemos los valores correctos en la matriz, podemos usarla para
varias operaciones como translacin, rotacin y escalado. El truco consiste
en que puede multiplicar dos matrices para producir una tercera, y esta
tendr el mismo efecto en los puntos 3d que aplicando las dos matrices
originales una despus de la otra. Por ejemplo, si tiene una matriz que
rota un punto, y otra que lo mueve en una direccin, puede combinarlas para
producir una matriz que realizara la rotacin y translacin en un paso.
Puede crear transformaciones extremadamente complejas de este modo,
teniendo que multiplicar cada punto 3d por una sola matriz.

Allegro hace trampa al implementar la estructura de la matriz. La rotacin y
el escalado de un punto 3d puede ser realizado con una matriz simple de 3x3,
pero para trasladar el punto y proyectarlo en la pantalla, la matriz tiene
que ser extendida a 4x4, y el punto extendido a una cuarta dimensin, al
aadir una coordenada extra: w=1. Esto es algo malo en trminos de
eficiencia, pero afortunadamente, es posible realizar una optimizacin. Dada
la siguiente matriz 4x4:

   ( a, b, c, d )
   ( e, f, g, h )
   ( i, j, k, l )
   ( m, n, o, p )

se puede observar un patrn de qu partes hacen qu. La rejilla 3x3 de
arriba a la izquierda implementa la rotacin y el escalado. Los tres valores
de arriba de la cuarta columna (d, h y l) implementan la translacin, y
siempre y cuando la matriz sea usada slo para transformaciones afines, m, n
y o sern siempre cero y p siempre ser 1. Si no sabe que significa 'afn',
lea a Foley & Van Damme: bsicamente cubre el escalado, la translacin y
rotacin del objeto pero no la proyeccin. Ya que Allegro usa una funcin
aparte para la proyeccin, las funciones de matriz slo tienen que servir
para la transformacin afn, lo que significa que no hay que guardar la fila
inferior de la matriz. Allegro asume que esta contiene (0,0,0,1), y por eso
optimiza las funciones de manipulacin de matrices.

Las matrices se almacenan en estructuras:

   typedef struct MATRIX     - matriz de punto fijo
   {
      fixed v[3][3];         - componente 3x3 de escalado y rotacin
      fixed t[3];            - componente x/y/z de translacin
   } MATRIX;
   
   typedef struct MATRIX_f   - matriz de coma flotante
   {
      float v[3][3];         - componente 3x3 de escalado y rotacin
      float t[3];            - componente x/y/z de translacin
   } MATRIX_f

extern MATRIX identity_matrix;
extern MATRIX_f identity_matrix_f;
   Variable global que contiene la matriz con identidad 'vaca'. Multiplicar
   por la matriz de identidad no tiene ningn efecto.

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);
   Construye una matriz de translacin, guardndola en m. Si se aplica a un
   punto (px, py, pz), esta matriz producir el punto (px+x, py+y, pz+z). En
   otras palabras: mueve las cosas.

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);
   Construye una matriz de escalado, almacenndola en m. Cuando se aplica a
   un punto (px, py, pz), esta matriz produce un punto (px*x, py*y, pz*z).
   En otras palabras, agranda o empequeece las cosas.

void get_x_rotate_matrix(MATRIX *m, fixed r);
void get_x_rotate_matrix_f(MATRIX_f *m, float r);
   Construye las matrices de rotacin del eje X, almacenndolas en m. Cuando
   se aplican a un punto, estas matrices lo rotarn sobre el eje X el ngulo
   especificado (en binario, 256 grados hacen un crculo).

void get_y_rotate_matrix(MATRIX *m, fixed r);
void get_y_rotate_matrix_f(MATRIX_f *m, float r);
   Construye las matrices de rotacin del eje Y, almacenndolas en m. Cuando
   se aplican a un punto, estas matrices lo rotarn sobre el eje Y el ngulo
   especificado (en binario, 256 grados hacen un crculo).

void get_z_rotate_matrix(MATRIX *m, fixed r);
void get_z_rotate_matrix_f(MATRIX_f *m, float r);
   Construye las matrices de rotacin del eje Z, almacenndolas en m. Cuando
   se aplican a un punto, estas matrices lo rotarn sobre el eje Z el ngulo
   especificado (en binario, 256 grados hacen un crculo).

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);
   Construye una matriz de transformacin que rotar puntos en todos los
   ejes los grados especificados. (en binario, 256 grados hacen un crculo).

void get_align_matrix(MATRIX *m, fixed xfront, yfront, zfront,
                                 fixed xup, fixed yup, fixed zup);
   Rota la matriz de tal forma que la alinea sobre las coordenadas de los
   vectores especificados (estos no tienen que ser normalizados o
   perpendiculares, pero up y front no pueden ser iguales). Un vector front
   de 1,0,0 y un vector up de 0,1,0 devolvern la matriz de identidad.

void get_align_matrix_f(MATRIX *m, float xfront, yfront, zfront,
                                   float xup, yup, zup);
   Versin en coma flotante de 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);
   Construye una matriz de transformacin que rotar puntos sobre todos los
   vectores x,y,z un ngulo especificado (en binario, 256 grados hacen un
   crculo).

void get_transformation_matrix(MATRIX *m, fixed scale,
                               fixed xrot, yrot, zrot, x, y, z);
   Construye una matriz de transformacin que rotar puntos en todos los
   ejes los ngulos especificados (en binario, 256 grados hacen un crculo),
   escalar el resultado (pasa el valor 1 si no quiere cambiar la escala),
   y entonces los trasladar a la posicin x, y, z requerida.

void get_transformation_matrix_f(MATRIX_f *m, float scale,
                                 float xrot, yrot, zrot, x, y, z);
   Versin en coma flotante de get_transformation_matrix().

void get_camera_matrix(MATRIX *m, fixed x, y, z, xfront, yfront, zfront,
                       fixed xup, yup, zup, fov, aspect);
   Construye la matriz de cmara para trasladar objetos del espacio a una
   vista normalizada del espacio, preparada para la proyeccin de
   perspectiva. Los parmetros x, y, z especifican la posicin de la cmara,
   xfront, yfront y zfront son los vectores 'de frente' que especifican
   hacia adonde apunta la cmara (estos pueden ser de cualquier tamao, no
   es necesaria la normalizacin), y xup, yup y zup son los vectores de la
   direccin 'arriba'. El parmetro fov especifica el campo de visin (el
   ancho del foco de la cmara) en binario, haciendo 256 grados un crculo.
   Para proyecciones tpicas, un campo de visin de entre 32 a 48 trabajara
   bien. Finalmente, la razn de aspecto es usada para el escalado en la
   dimensin Y relativamente al eje X, para que pueda ajustar las
   proporciones de la imagen final (ponga a uno para no escalar).

void get_camera_matrix_f(MATRIX_f *m, float x, y, z, xfront, yfront,zfront,
                         float xup, yup, zup, fov, aspect);
   Versin en coma flotante de 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);
   Rutina optimizada para trasladar una matriz ya generada: esto
   simplemente aade el 'offset' de translacin, por lo que no hay que crear
   dos matrices temporales y multiplicarlas.

void qscale_matrix(MATRIX *m, fixed scale);
void qscale_matrix_f(MATRIX_f *m, float scale);
   Rutina optimizada para escalar una matriz ya generada: esto simplemente
   aade el factor de escalacin, por lo que no hay que crear dos matrices
   temporales y multiplicarlas.

void matrix_mul(const MATRIX *m1, MATRIX *m2, MATRIX *out);
void matrix_mul_f(const MATRIX_f *m1, MATRIX_f *m2, MATRIX_f *out);
   Multiplica dos matrices, guardando el resultado en out (que puede ser
   un duplicado de una de las dos mtrices de entrada, pero es ms rpido
   cuando las entradas y la salida son todas distintas). La matriz
   resultante tendr el mismo efecto que la combinacin de m1 y m2, p.ej
   cuando son aplicadas en un punto, (p * out) = ((p * m1) * m2). Cualquier
   nmero de transformaciones se puede concatenar de esta forma. Fjese que
   la multiplicacin de matrices no es communtaiva, as
   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);
   Calcula la longitud del vector (x, y, z), usando ese buen teorema de
   Pitgoras.

void normalize_vector(fixed *x, fixed *y, fixed *z);
void normalize_vector_f(float *x, float *y, float *z);
   Convierte un vector (*x, *y, *z) a un vector normalizado. Este apunta en
   la misma direccin que el vector original, pero tiene una longitud de
   uno.

fixed dot_product(fixed x1, y1, z1, x2, y2, z2);
float dot_product_f(float x1, y1, z1, x2, y2, z2);
   Calcula el producto escalar (x1, y1, z1) . (x2, y2, z2), devolviendo el
   resultado.

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);
   Calcula el producto vectorial (x1, y1, z1) x (x2, y2, z2), almacenando el
   resultado en (*xout, *yout, *zout). El resultado es perpendicular a los
   dos vectores de entrada, para que pueda ser usado para generar las
   normales de los polgonos.

fixed polygon_z_normal(const V3D *v1, V3D *v2, V3D *v3);
float polygon_z_normal_f(const V3D_f *v1, V3D_f *v2, V3D_f *v3);
   Encuentra la componente Z de la normal de un vector de tres vrtices
   especificados (que deben ser parte de un polgono convexo). Esto es usado
   principalmente en la ocultacin de caras. Las caras traseras de un
   poliedro cerrado nunca son visibles al espectador, y por tanto no
   necesitan ser dibujadas. Esto puede ocultar aproximadamente la mitad de
   los polgonos de una escena. Si la normal es negativa, el polgono se
   puede eliminar, si es cero, el polgono est perpendicular a la pantalla.

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);
   Multiplica el punto (x, y, z) por la transformacin de la matriz m,
   almacenando el resultado en el punto (*xout, *yout, *zout).

void set_projection_viewport(int x, int y, int w, int h);
   Ajusta el punto de visin usado para escalar la salida de la funcin
   persp_project(). Pase las dimensiones de la pantalla y el rea donde la
   quiere dibujar, que tpicamente ser 0, 0, SCREEN_W, SCREEN_H.

void persp_project(fixed x, y, z, *xout, *yout);
void persp_project_f(float x, y, z, *xout, *yout);
   Proyecta el punto 3d (x, y, z) del espacio sobre una pantalla 2d,
   almacenando el resultado en (*xout, *yout) usando los parmetros
   anteriormente ajustados por set_projection_viewport(). Esta funcin
   proyecta desde la pirmide de vista normalizada, que tiene una cmara en
   el origen apuntando al eje z positivo. El eje x va de izquierda a
   derecha, y va de arriba a abajo, y z se incrementa con la profundidad de
   la pantalla. La cmara tiene un ngulo de visin de 90 grados, es
   decir, los planos x=z y -x=z sern los bordes izquierdo y derecho de la
   pantalla, y los planos y=z y -y=z sern la parte superior e inferior de
   la pantalla. Si quiere un campo de visin diferente a la posicin de la
   cmara, debera transformar todos sus objetos con la matriz de visin
   apropiada. Ejemplo, para obtener el efecto de haber girado la cmara 10
   grados a la izquierda, rote todos sus objetos 10 grados a la derecha.



=======================================================================
============ 31 Rutinas matemticas para usar cuaterniones ============
=======================================================================

Los cuaterniones son una forma alternativa de representar la parte de
rotacin de una transformacin, y pueden ser ms fciles de manipular que las
matrices. Como con una matriz, usted puede codificar transformaciones
geomtricas en una, concatenar varias de ellas para mezclar mltiples
transformaciones, y aplicarlas a un vector, pero slo pueden almacenar
rotaciones puras. La gran ventaja es que puede interpolar precisamente entre
dos cuaterniones para obtener una rotacin parcial, evitando los enormes
problemas de la interpolacin ms convencional con ngulos eulerianos.

Los cuaterniones slo poseen versiones de punto flotante, sin ningn sufijo
"_f". Por otro lado, la mayora de las funciones de cueterniones se
corresponden con una funcin matricial que realiza una operacin similar.

Cuaternin significa 'de cuatro partes', y es exactamente eso. Aqu est la
estructura:

   typedef struct QUAT
   {
      float w, x, y, z;
   }

Usted se divertir mucho buscando el significado real de estos nmeros, pero
eso est ms all del alcance de esta documentacin. Los cuaterniones
funcionan -- crame.

extern QUAT identity_quat;
   Variable global que contiene el cuaternin identidad 'que no hace nada'.
   Multiplicar por el cuaternin identidad no tiene efecto alguno.

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);
   Construye cuaterniones de ejes de rotacin, almacenndolos en q. Cuando
   sean aplicados a un punto, stos cuaterniones lo rotarn sobre el eje
   relevante el ngulo especificado (dado en binario, 256 grados forman un
   crculo).

void get_rotation_quat(QUAT *q, float x, float y, float z);
   Construye un cuaternin que rotar puntos alrededor de los tres ejes las
   cantidades especificadas (dadas en binario, 256 grados forman un crculo).

void get_vector_rotation_quat(QUAT *q, float x, y, z, float a);
   Construye un cuaternin que rotar puntos alrededor del vector x,y,z el
   ngulo especificado (dado en binario, 256 grados forman un crculo).

void quat_to_matrix(const QUAT *q, MATRIX_f *m);
   Construye una matriz de rotacin a partir de un cuaternin.

void matrix_to_quat(const MATRIX_f *m, QUAT *q);
   Construye un cuaternin a partir de una matriz de rotacin. La translacin
   es descartada durante la conversin. Use get_align_matrix_f() si la matriz
   no est ortonormalizada, porque de otra forma podran pasar cosas
   extraas.

void quat_mul(const QUAT *p, const QUAT *q, QUAT *out);
   Multiplica dos cuaterniones, almacenando el resultado en out. El
   cuaternin resultante tendr el mismo efecto que la combinacin de p y q,
   es decir, cuando es aplicado a un punto, (punto * out) = ((punto * p) *
   q). Cualquier cantidad de rotaciones pueden ser concatenadas de sta
   manera. Note que la multiplicacin del cuaternin no es conmutativa, es
   decir que quat_mul(p, q) != quat_mul(q, p).

void apply_quat(const QUAT *q, float x, y, z, *xout, *yout, *zout);
   Multiplica el punto (x, y, z) por el cuaternin q, almacenando el
   resultado en (*xout, *yout, *zout). Esto es un poquito ms lento que
   apply_matrix_f(), as que selo para trasladar unos pocos puntos. Si usted
   tiene muchos puntos, es mucho ms eficiente llamar a quat_to_matrix() y
   entonces usar apply_matrix_f().

void quat_interpolate(const QUAT *from, QUAT *to, float t, QUAT *out);
   Construye un cuaternin que representa una rotacin entre from y to. El
   argumento t puede ser cualquiera entre 0 y 1, y representa dnde estar
   el resultado entre from y to. 0 devuelve from, 1 devuelve to, y 0.5
   devolver una rotacin exactamente en la mitad. El resultado es copiado a
   out. Esta funcin crear una rotacin corta (menos de 180 grados) entre
   from y to.

void quat_slerp(const QUAT *from, QUAT *to, float t, QUAT *out, int how);
   Igual que quat_interpolate(), pero permite ms control sobre cmo es hecha
   la rotacin. El parmetro how puede ser alguno de estos valores:

      QUAT_SHORT  - como quat_interpolate(), usa el camino ms corto
      QUAT_LONG   - la rotacin ser mayor que 180 grados
      QUAT_CW     - rotacin horaria vista desde arriba
      QUAT_CCW    - rotacin antihoraria vista desde arriba
      QUAT_USER   - los cuaterniones son interpolados exactamente como
                    son dados.



========================================
============ 32 Rutinas GUI ============
========================================

Allegro posee un gestor de dilogos orientados a objetos que originalmente se
basa en el sistema GEM del Atari (form_do(), objc_draw(), etc: programadores
veteranos del ST saben de lo que estoy hablando :-) Puede usar el GUI tal y
como esta para crear interfaces simples para cosas como el programa test y la
utilidad grabber, o puede usarlo como base para sistemas ms complicados que
cree. Allegro le deja definir sus propios tipos de objetos y escribir nuevos
procesos de dilogo, por lo que tendr control total sobre los aspectos
visuales de la interfaz mientras todava usa Allegro para controlar el ratn,
teclado, joystick, etc.

Un dilogo GUI se almacena como un array de objetos DIALOG, de los cuales
cada uno cuenta con los siguientes parmetros:

   typedef struct DIALOG
   {
      int (*proc)(int, DIALOG *, int); - proceso del dilogo (controlador de
                                         mensajes)
      int x, y, w, h;                  - posicin y tamao del objeto
      int fg, bg;                      - colores de letra y fondo
      int key;                         - atajo ASCII del teclado
      int flags;                       - variable con el estado del objeto
      int d1, d2;                      - selos para lo que quiera
      void *dp, *dp2, *dp3;            - punteros a datos especficos del objeto
   } DIALOG;

El array debe acabar con un objeto que tiene el proceso de dilogo puesto
a NULL.

El campo de bits puede contener cualquier combinacin de los siguientes bits:

   D_EXIT          - este objeto debe cerrar el dilogo al activarse
   D_SELECTED      - este objeto est seleccionado
   D_GOTFOCUS      - este objeto tiene el foco de entrada
   D_GOTMOUSE      - el ratn esta actualmente encima del objeto
   D_HIDDEN        - este objeto est oculto e inactivo
   D_DISABLED      - este objeto est de color gris e inactivo
   D_DIRTY         - este objeto necesita ser redibujado
   D_INTERNAL      - no use esto! Es para uso interno de la biblioteca...
   D_USER          - cualquier valor mltiplo de dos mayor que ste esta
                     libre para que lo use

Cada objeto es controlado por un proceso de dilogo, que se almacena en el
puntero proc. Este ser llamado por el gestor de dilogos cuando se produzca
alguna accin que involucre al objeto, o puede llamarlo directamente con la
funcin object_message(). El proceso de dilogo debe seguir la siguiente
forma:

   int foo(int msg, DIALOG *d, int c);

Se le pasar una variable (msg) indicando qu debe hacer, un puntero al
objeto concerniente (d), y si msg es MSG_CHAR o MSG_XCHAR, la tecla que ha
sido pulsada (c). Fjese que d es un puntero a un objeto especifico y no al
dilogo entero.

El proceso del dilogo debera devolver uno de los siguientes valores:

   D_O_K          - estado normal de retorno
   D_CLOSE        - le dice al gestor de dilogos que cierre el dilogo
   D_REDRAW       - le dice al gestor de dilogos que redibuje el dilogo
   D_REDRAWME     - dice al gestor de dilogos que redibuje el objeto actual
   D_WANTFOCUS    - requiere que se le de el foco de entrada al objeto
   D_USED_CHAR    - MSG_CHAR y MSG_XCHAR devuelven esto si se uso una tecla

Los procesos de dilogo se pueden llamar con cualquiera de estos mensajes:

MSG_START:
   Le dice al objeto que se inicialice. El gestor de dilogo manda esto a
   todos los objetos del dilogo justo antes de mostrarlo.

MSG_END:
   Se manda a todos los objetos cuando se cierra un dilogo, permitindoles
   que hagan los procesos de limpieza que necesiten.

MSG_DRAW:
   Le dice al objeto que se dibuje en pantalla. El puntero del ratn se
   desactivara cuando este mensaje sea mandado, para que el cdigo de
   dibujado no se preocupe por l.

MSG_CLICK:
   Informa al objeto que un botn del ratn a sido pulsado mientras el
   ratn estaba encima del objeto. Normalmente el objeto realizar su
   propio seguimiento del ratn mientras el botn est pulsado, y slo
   volver de este controlador de mensaje cuando se suelte el botn.

MSG_DCLICK:
   Se manda cuando el usuario hace un doble click en un objeto. Primero se
   manda el mensaje MSG_CLICK cuando se presiona el botn por primera vez, y
   entonces MSG_DCLICK si se suelta y vuelve a presionar otra vez en un
   corto periodo de tiempo.

MSG_KEY:
   Mandado cuando el atajo de teclado del objeto se presiona, o si se pulsa
   enter, espacio, o algn botn del joystick cuando el objeto tiene el foco
   de entrada.

MSG_CHAR:
   Cuando se pulsa una tecla, este mensaje es mandado al objeto que tiene el
   foco de entrada, con un formato de cdigo de carcter igual al de la
   funcin readkey() (valor ASCII en el byte bajo, scancode en el byte alto)
   como parmetro c. Si el objeto trata con la pulsacin de teclas debera
   devolver D_USED_CHAR, en caso contrario debera devolver D_O_K para
   permitir operar al interfaz de teclado por defecto. Si necesita acceder a
   la entrada de un carcer Unicode, debera usar MSG_UCHAR en vez de
   MSG_CHAR.

MSG_UCHAR:
   Si un objeto ignora la entrada MSG_CHAR, este mensaje ser mandado
   inmediatemente despus de l, pasando el valor completo de la tecla
   en Unicode como parmetro c. Esto le permite leer cdigos de carcteres
   mayores que 255, pero no puede decirle nada sobre el scancode: si
   necesita saberlo, use MSG_CHAR en lugar de MSG_UCHAR. Este manejador debe
   devolver D_USED_CHAR si proces la entrada, o D_O_K en otro caso.

MSG_XCHAR:
   Cuando se pulsa una tecla, Allegro mandar MSG_CHAR y MSG_UCHAR al objeto
   que tenga el foco de entrada. Si este objeto no procesa la tecla (ej.
   devuelve D_O_K en vez de D_USED_CHAR), el gestor de dilogos buscar un
   objeto con un atajo de teclado asociado en el campo key, mandndole un
   MSG_KEY. Si esto falla, mandar un MSG_XCHAR al resto de los objetos
   del dilogo, permitindoles responder a pulsaciones de tecla especiales
   incluso cuando no tienen el foco de entrada. Normalmente debera ignorar
   este mensaje (devolver D_O_K en vez de D_USED_CHAR), en cuyo caso Allegro
   realizar las acciones por defecto tales como mover el foco de entrada
   en respuesta a los cursores y cerrar el dilogo si se pulsa ESC.

MSG_WANTFOCUS:
   Determina si un objeto quiere recibir el foco de entrada. Deber devolver
   D_WANTFOCUS si lo desea, o D_O_K si no esta interesado en recibir datos
   del usuario.

MSG_GOTFOCUS:
MSG_LOSTFOCUS:
   Es mandado cuando un objeto gana o pierde el foco de entrada. Estos
   mensajes siempre son seguidos por un MSG_DRAW, para dejar que los objetos
   se redibujen de manera diferente. Si devuelve D_WANTFOCUS en respuesta a
   un evento MSG_LOSTFOCUS, esto le permitir a su objeto quedarse con el
   foco de entrada incluso si el ratn deja de estar sobre l y se pone
   sobre el fondo u otro objeto inerte, por lo que solamente perder el foco
   de entrada cuando otro objeto est preparado para cogerlo (este truco es
   usado por el objeto d_edit_proc()).

MSG_GOTMOUSE:
MSG_LOSTMOUSE:
   Es mandado cuando el ratn se pone o quita de un objeto. A diferencia de
   los mensajes de foco, a estos no les sigue un MSG_DRAW, por lo que si el
   objeto se dibuja de forma diferente cuando el ratn esta encima suyo, es
   responsable de redibujarse l solo como respuesta a estos mensajes.

MSG_IDLE:
   Es mandado cuando el dilogo de gestor no tiene nada mejor que hacer.

MSG_RADIO:
   Es mandado por botones de radio para deseleccionar otros botones en el
   mismo grupo cuando son pulsados. El nmero del grupo se pasa en el
   parmetro del mensaje c.

MSG_WHEEL:
   Enviado al objeto que tenga el foco de entrada cada vez que se mueve la
   rueda del ratn. El parmetro c de mensaje contiene el nmero de clicks.

MSG_LPRESS, MSG_MPRESS, MSG_RPRESS:
   Enviado cuando el botn correspondiente del ratn es presionado.

MSG_LRELEASE, MSG_MRELEASE, MSG_RRELEASE:
   Enviado cuando el botn correspondiente del ratn es soltado.

MSG_USER:
   El primer valor de mensaje libre. Cualquier nmero a partir de aqu
   (MSG_USER, MSG_USER+1, MSG_USER+2, ... MSG_USER+n) es libre para lo que
   quiera.

Allegro trae varios procesos de dilogo estndar. Puede usarlos tal como
vienen para crear una interfaz de objetos simples, o puede usarlos desde
sus propios proceses de dilogo, resultando en una especie de herencia de
objetos. Por ejemplo, podra hacer un objeto que llama d_button_proc para
dibujarse, pero controla el mensaje de pulsacin del botn del ratn de
forma diferente, o un objeto que llama d_button_proc para cualquier cosa
excepto para dibujarse a si mismo, por lo que se comportara como un botn
normal pero podra ser completamente diferente.

Desde la versin 3.9.33 (CVS) de Allegro, algunos objetos y mens de la
interfaz grfica de usuario son dibujados de forma diferente en comparacin
con versiones anteriores de Allegro. Los cambios son:

   Las sombras bajo d_shadow_box_proc y d_button_proc son siempre negras.

   El cambio ms importante (y visible inmediatamente), es que algunos
   objetos se dibujan ms pequeos. La diferencia es exctamente un pixel
   tanto vertical como horizontalmente, comparando con versiones anteriores.
   La razn es que en versiones anteriores, estos objetos eran demasiado
   grandes para la pantalla - su tamao era d->;w+1 y d->;h+1 en pixels (y no
   d->;w y d->;h, como debera ser). Este cambio afecta a los siguientes
   objetos:

      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.

   Cuando quiera convertir dilogos antiguos para que visualmente sean
   iguales al compilar con la nueva versin de Allegro, simplemente
   incremente el tamao un pixel en los campos de anchura y altura.

   Cuando un item del men (no en un men de barra) tiene un men hijo,
   hay una pequea flecha junto al nombre del men hijo, apuntando a la
   derecha - para que los usuarios vean que ese men tiene submens - y
   no es necesario usar nombres de men como por ejemplo "Nuevo...", para
   indicar que el elemento tiene un submen. El submen ser dibujado a la
   derecha del padre, intentando no sobreescribirlo.


int d_clear_proc(int msg, DIALOG *d, int c);
   Esto simplemente borra la pantalla al ser dibujado. Util como el primer
   objeto de un dilogo.

int d_box_proc(int msg, DIALOG *d, int c);
int d_shadow_box_proc(int msg, DIALOG *d, int c);
   Estos dibujan cajas en la pantalla, con o sin sombra.

int d_bitmap_proc(int msg, DIALOG *d, int c);
   Esto dibuja un bitmap en la pantalla, que deber ser apuntado por el
   campo dp.

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);
   Estos dibujan texto en la pantalla. El campo dp debe apuntar a la cadena
   de texto a visualizar. d_ctext_proc() centra la cadena alrededor de la
   coordenada x, y d_rtext_proc la alinea a la derecha. Todos los carcteres
   '&' de la cadena sern reemplazados por lneas debajo del siguiente
   carcter, para ensear los atajos de teclado (tal y como en MS Windows).
   Para ensear el caracter normal, ponga "&&". Para dibujar el texto con
   otra cosa que no sea la fuente por defecto, ajuste el campo dp2 para que
   apunte a una fuente propia.

int d_button_proc(int msg, DIALOG *d, int c);
   Un botn objeto (el campo dp apunta a una cadena de texto). Este objeto
   puede ser seleccionado pinchando sobre l con el ratn o presionando su
   atajo de teclado. Si se pone el bit D_EXIT, el seleccionarlo provocar el
   cierre del dilogo. Si no, encender y apagar el dilogo. Como en
   d_text_proc(), puede usar el caracter '&' para ensear el atajo de
   teclado del botn.

int d_check_proc(int msg, DIALOG *d, int c);
   Este es un ejemplo de cmo puede derivar objetos desde otros objetos. La
   mayora de la funcionalidad viene de d_button_proc(), pero se visualiza
   como un recuadro a marcar. Si el campo d1 no es cero, el texto se
   imprimir a la derecha de la marca, en caso contrario estar a la
   izquierda.

   Nota: el ancho del objeto debe reservar espacio tanto para el texto como
   para el recuadro (que es cuadrado, con lados del mismo tamao que la
   altura del objeto).

int d_radio_proc(int msg, DIALOG *d, int c);
   Un objeto de botn de radio. Un dilogo puede contener cualquier nmero
   de grupos de botones de radio: el seleccionar un botn de radio provoca
   que los otros botones del mismo grupo se desactiven. El campo dp apunta a
   una cadena de texto, d1 requiere el nmero de grupo especifico, y d2 es el
   estilo del botn (0=crculo, 1=cuadrado).

int d_icon_proc(int msg, DIALOG *d, int c);
   Un botn bitmap. El color fg es usado por la lnea de puntos que ensea
   el foco, y el color bg hace la sombra que rellena la parte superior e
   izquierda del botn cuando este se presiona. d1 es la "profundidad", es
   decir, el nmero de pixels que el icono ser movido abajo a la derecha
   cuando se seleccione (por defecto 2) si no hay imagen "seleccionada". d2
   es la distancia entre los puntos de la lnea del foco. dp apunta a un
   bitmap para el icono, mientras que dp2 y dp3 son las imgenes de botn
   seleccionado y no seleccionado (esto es opcional, puede ser NULL).

int d_keyboard_proc(int msg, DIALOG *d, int c);
   Este es un objeto invisible para implementar atajos de teclado. Puede
   poner un cdigo ASCII en el campo de la tecla del dilogo del objeto (un
   caracter como 'a' responde a la pulsacin de tecla, un nmero del 1 al 26
   responde a Ctrl+una tecla a-z), o puede poner un scancode del teclado en
   el campo d1 y/o d2. Cuando una de estas teclas es presionada, el objeto
   llamar a la funcin apuntada por dp. Esto debera devolver un entero, el
   cual se pasar de vuelta al gestor de dilogo, para que pueda devolver
   D_O_K, D_REDRAW, D_CLOSE, etc.

int d_edit_proc(int msg, DIALOG *d, int c);
   Un objeto de texto editable (el campo dp apunta a la cadena de texto).
   Cuando tiene el foco de entrada (obtenido al pinchar sobre el objeto con
   el ratn), se puede teclear texto en el objeto. El campo d1 indica el
   nmero mximo de carcteres que se aceptaran, y d2 es la posicin del
   cursor dentro de la cadena de texto.

int d_list_proc(int msg, DIALOG *d, int c);
   Un objeto caja de lista. Esto permite al usuario ir hacia arriba o abajo
   de la lista de tems y seleccionar uno pinchando con el ratn o usando las
   teclas. Si el bit D_EXIT est activado, haciendo doble click en la lista
   de tems cerrar el dilogo. El ndice del objeto seleccionado se
   encuentra en el campo d1, y d2 es usado para indicar hasta dnde se ha
   desplazado la lista de tems. El campo dp apunta a una funcin que ser
   llamada para obtener informacin sobre los contenidos de la lista. Esto
   debera seguir el modelo:

      char *foobar(int index, int *list_size);

   Si index es cero o positivo, la funcin debe devolver un puntero a la
   cadena que debe ensearse en la posicin index en la lista. Si index es
   negativo, debe devolver NULL y en list_size debe poner el nmero de tems
   de la lista.

   Para crear una lista de seleccin mltiple, haga apuntar dp2 a un array
   de variables de un byte que indican el estado de seleccin de cada tem de
   la lista (distinto de cero para entradas seleccionadas). Esta tabla debe
   ser al menos tan grande como el nmero de objetos de la lista!

int d_text_list_proc(int msg, DIALOG *d, int c);
   Igual que d_list_proc, pero permite que el usuario escriba algunos de los
   primeros carcteres de una entrada de la caja de listas para as
   seleccionarlo. Se usa dp3 internamente, as que no deber poner nada
   importante ah por s mismo.

int d_textbox_proc(int msg, DIALOG *d, int c);
   Un objeto caja de texto. El campo dp apunta al texto que debe ensearse en
   la caja. Si el texto es largo, habr una barra de desplazamiento vertical
   a la derecha del objeto que podr ser usada para mover el texto dentro de
   la caja. El valor por defecto es imprimir el texto con ajuste de anchura a
   nivel de palabra, pero si se activa el bit D_SELECTED, el texto se
   imprimir con ajuste de anchura a nivel de carcter. El campo d1 se usa
   internamente para guardar el nmero de lneas de texto, y d2 es usado para
   guardar hasta dnde se ha desplazado el texto.

int d_slider_proc(int msg, DIALOG *d, int c);
   Una barra de desplazamiento. Este objeto tiene un valor en d2, con rango
   de 0 a d1. Ensear una barra de desplazamiento vertical si h es ms
   grande o igual a w, de otro modo ensear una barra horizontal. El campo
   dp puede contener un bitmap opcional que usar la barra de desplazamiento,
   y dp2 puede contener una funcin opcional de callback, que ser llamada
   cada vez que d2 cambie. La funcin callback debera seguir el prototipo:

      int function(void *dp3, int d2);

   El objeto d_slider_proc devolver el valor de la funcin callback.

int d_menu_proc(int msg, DIALOG *d, int c);
   Este objeto es una barra de men que abre mens hijos cuando se pincha en
   l o cuando alguna combinacin alt+tecla es pulsada y se corresponde con
   algn atajo del men. El objeto ignora muchos de los campos de la
   estructura de dilogo, particularmente el color se coge de las variables
   gui_*_color, y el ancho y alto se calculan automticamente (los cambos w
   y h de la estructura DIALOG slo se usan como tamao mnimo). El campo dp
   apunta a un array de estructuras de men: mire do_menu() para ms
   informacin. El nivel de arriba del men ser visualizado como una barra
   horizontal, pero cuando aparezcan los mens hijos, aparecern con el
   formato vertical usual usado por do_menu(). Cuando un tem del men es
   seleccionado, el valor de retorno de la funcin del men se pasa al
   gestor de dilogo, para que las funciones de sus mens puedan devolver
   D_O_K, D_REDRAW, o D_CLOSE.

int d_yield_proc(int msg, DIALOG *d, int c);
   Un objeto ayudante invisible que rechaza rebanadas de tiempo de la CPU
   (si el sistema lo soporta) cuando la interfaz no tiene nada ms que
   hacer que esperar las acciones del usuario. Debera poner al menos un
   objeto de este tipo en cada array ya que podra ser necesario en sistemas
   con un algoritmo de planificacin de tareas inusual (por ejemplo QNX)
   para hacer la interfaz totalmente responsiva al usuario.

El comportamiento del gestor de dilogos se controla con las siguientes
variables:

extern int gui_mouse_focus;
   Si esta activado, el foco de entrada sigue al puntero del ratn, de otro
   modo, un click es requerido para mover el foco de entrada.

extern int gui_fg_color, gui_bg_color;
   Los colores de primer plano y fondo de los dilogos estndar (alertas,
   mens, y el selector de ficheros). Por defecto son 255 y 0.

extern int gui_mg_color;
   El color usado para ensear los dilogos en gris (los que tienen el
   bit D_DISABLED activado). Por defecto es 8.

extern int gui_font_baseline;
   Si se pone a un valor distinto de cero, ajusta los subrayados mostrados
   por los atajos de teclado para que igualen el tamao de las letras de la
   fuente que sobresalgan por debajo.

extern int (*gui_mouse_x)();
extern int (*gui_mouse_y)();
extern int (*gui_mouse_z)();
extern int (*gui_mouse_b)();
   Funciones de enganche, usadas por las rutinas GUI siempre que necesiten
   acceder al estado del ratn. Por defecto stas devuelven copias de
   las variables mouse_x, mouse_y, mouse_z y mouse_b, pero pueden ser
   usadas para situar o escalar la posicin del ratn, o para leer datos
   de una fuente totalmente diferente.

Puede cambiar el puntero global a 'font' para hacer que los objetos del
GUI usen otra cosa que la fuente estndar 8x8. Los procesos estndar de
dilogo, los mens, las cajas de alerta, trabajarn con fuentes de cualquier
tamao, pero el dilogo gfx_mode_select() aparecern mal con cualquier cosa
que no sean fuentes de 8x8.

int gui_textout(BITMAP *bmp, const char *s, int x, y, color, centre);
   Funcin de ayuda usada por las rutinas GUI. Dibuja una cadena de texto en
   la pantalla, interpretando el caracter '&' como el subrayado para ensear
   los atajos de teclado. Devuelve el ancho de la cadena en pixels.

int gui_strlen(const char *s);
   Funcin de ayuda usada por las rutinas GUI. Devuelve la longitud de una
   cadena de texto en pixels, ignorando los carcteres '&'.

void position_dialog(DIALOG *dialog, int x, int y);
   Mueve un array de objetos de dilogo a la posicin de pantalla
   especificada (indicando la esquina superior izquierda del dilogo).

void centre_dialog(DIALOG *dialog);
   Mueve un array de dilogos de objetos para que estn centrados en la
   pantalla.

void set_dialog_color(DIALOG *dialog, int fg, int bg);
   Pone el color de primer plano y fondo de un array de dilogo de objetos.

int find_dialog_focus(DIALOG *dialog);
   Busca el dilogo para el objeto que tiene el foco de entrada, devolviendo
   un ndice o -1 si no hay foco de entrada. Esto es til cuando est
   llamando a do_dialog() varias veces seguidas y quiere dejar el foco de
   entrada en el mismo lugar que cuando se enseo el dilogo la ultima vez,
   por lo que pueda llamar a do_dialog(dlg, find_dialog_focus(dlg));

int offer_focus(DIALOG *d, int obj, int *focus_obj, int force);
   Ofrece el foco de entrada a un objeto particular. Normalmente esta funcin
   enva el mensaje MSG_WANTFOCUS para preguntar si el objeto desea aceptar
   el foco. Pero si pasa un valor distinto de cero como argumento force,
   estr indicando a la funcin que el objeto debe tener el foco de entrada.

int object_message(DIALOG *dialog, int msg, int c);
   Enva un mensaje a un objeto y devuelve la respuesta generada. Recuerde
   que el primer parmetro es el objeto del dilogo (no el array completo)
   al que desea enviar el mensaje. Por ejemplo, para hacer que el segundo
   objeto del dilogo se dibuje, podra escribir:

      object_message(&dialog[1], MSG_DRAW, 0);

int dialog_message(DIALOG *dialog, int msg, int c, int *obj);
   Manda un mensaje a todos los objetos de un array. Si alguno de los
   procesos de dilogo devuelve otro valor que no sea D_O_K, la funcin
   devuelve el valor y hace apuntar a obj al ndice del objeto que produjo
   ese mensaje.

int broadcast_dialog_message(int msg, int c);
   Manda un mensaje a todos los objetos del dilogo activo. Si cualquiera de
   los procesos de dilogo devuelve otros valores que no sean D_O_K, devuelve
   ese valor.

int do_dialog(DIALOG *dialog, int focus_obj);
   La funcin bsica del gestor de dilogo. Esta ensea el dilogo (un
   array de objetos de dilogo, acabados por uno con el proceso de dilogo
   puesto a NULL), y pone el foco de entrada a focus_obj (-1 si no quiere
   que nada tenga el foco de entrada). La funcin interpreta la entrada del
   usuario y despacha mensajes a medida que se requiera, hasta que uno de los
   procesos de dilogo le dice que lo cierre. Entonces devuelve el ndice del
   objeto que caus el cierre.

int popup_dialog(DIALOG *dialog, int focus_obj);
   Como do_dialog(), pero almacena los datos de la pantalla antes de dibujar
   el dilogo y los recupera cuando el dilogo es cerrado. El rea de
   pantalla a guardar es calculada segn las dimensiones del primero objeto
   en el dilogo, por lo que el resto de los objetos deben estar dentro de
   l.

DIALOG_PLAYER *init_dialog(DIALOG *dialog, int focus_obj);
   Esta funcin da acceso de bajo nivel a la misma funcionalidad que
   do_dialog(), pero le permite combinar la caja de dilogo con sus propias
   estructuras de objeto. Inicializa un dilogo, devolviendo un puntero al
   objeto reproductor que puede ser usado con update_dialog() y
   shutdown_dialog(). Con estas funciones, puede implementar su propia
   versin de do_dialog() con las lneas:

      DIALOG_PLAYER *player = init_dialog(dialog, focus_obj);

      while (update_dialog(player))
         ;

      return shutdown_dialog(player);

int update_dialog(DIALOG_PLAYER *player);
   Actualiza el estado de un dilogo de objeto devuelto por init_dialog().
   Devuelve TRUE si el dilogo sigue activo, o FALSE si se ha cerrado. Si
   devuelve FALSE, depende de usted llamar a shutdown_dialog() o continuar
   con la ejecucin. El objeto que requiri la salida puede ser determinado
   desde el campo player->;obj.

int shutdown_dialog(DIALOG_PLAYER *player);
   Destruye el player de dilogo de objeto devuelto por init_dialog(),
   devolviendo el objeto que caus la salida (esto es lo mismo que el valor
   de do_dialog()).

extern DIALOG *active_dialog;
   Puntero global al dilogo activado ms recientemente. Esto puede ser til
   si un objeto necesita recorrer la lista de dilogos "hermanos".

Los mens emergentes o desplegables son creados como un array de la
estructura:

   typedef struct MENU
   {
      char *text;            - texto a visualizar por el tem del men
      int (*proc)();         - llamado cuando el tem del men es
                               seleccionado
      struct MENU *child;    - men hijo anidado
      int flags;             - estado seleccionado o deseleccionado
      void *dp;              - puntero a datos que necesite
   } MENU;

Cada tem del men contiene una cadena de texto. Puede usar el caracter '&'
para indicar el atajo del teclado, o puede ser una cadena de texto de tamao
cero para visualizar el tem como una barra divisoria no seleccionable. Si
la cadena contiene un caracter de tabulacin "\t", el texto que sigue ser
justificado a la derecha, por ejemplo para ensear informacin sobre el
atajo del teclado. El puntero proc es una funcin que ser llamada cuando el
tem del men sea seleccionado, y child apunta a otro men, permitindole
hacer mens anidados. proc y child pueden ser ambos NULL. La funcin proc
devuelve un entero que es ignorado si el men fue llamado por do_menu(), pero
que es devuelto al gestor de dilogo si fue creado por un objeto
d_menu_proc(). El array de tems del men se cierra con una entrada con el
campo text puesto a NULL.

Los tems del men pueden ser deseleccionados (en gris) activando el bit
D_DISABLED en el campo flags, y pueden ensear un smbolo de marcado si se
activa el bit D_SELECTED. Con la alineacin y fuente por defecto, la marca
sobreescribira el texto del men, por lo que si va a usar tems de men
con smbolo de marca, seria una buena idea prefijar todas sus opciones con
un caracter de espacio o dos, para estar seguro de que hay suficiente sitio
para el smbolo de marcado.

int do_menu(MENU *menu, int x, int y)
   Ensea y anima el men emergente en la pantalla en las coordenadas
   especificadas (estas sern ajustadas si el men no entra enteramente en
   la pantalla). Devuelve el ndice del tem de men seleccionado, o -1 si el
   men fue cancelado. Fjese que el valor de retorno no puede indicar una
   seleccin de mens hijo, por lo que tendr que usar funciones "callback"
   si quiere mens multi-nivel.

extern MENU *active_menu;
   Cuando se activa una llamada de vuelta, esta variable ser puesta al
   valor del tem seleccionado, para que su rutina pueda determinar desde
   dnde fue llamada.

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);
   Si las ajusta, estas funciones sern llamadas cuando un men necesite ser
   dibujado, por lo que puede cambiar el aspecto de los mens.

   A gui_menu_draw_menu() se le pasar la posicin y tamao del men. Debera
   dibujar el fondo del men en la pantalla (screen).

   gui_menu_draw_menu_item() ser llamado una vez por cada elemento del men
   que debe ser dibujado. bar ser distinto de cero si el elemento es parte
   de una barra de men horizontal del nivel superior, y sel ser distinto
   de cero si el elemento del men est seleccionado. Tambin debera ser
   dibujado en la pantalla (screen).

int alert(const char *s1, *s2, *s3, const char *b1, *b2, int c1, c2);
   Ensea una caja de alerta emergente, conteniendo tres lneas de texto
   (s1-s3), y con uno o dos botones. El texto de los botones se pasa en b1 y
   b2 (b2 puede ser NULL), y los atajos de teclado se pasan en c1 y c2.
   Devuelve 1 o 2 dependiendo de que botn fue pulsado. Si la alerta se
   aborta pulsando ESC cuando ESC no es uno de los atajos del teclado, se
   trata como si se hubiese pulsado el segundo botn (esto es consistente
   con la tpica alerta "Ok", "Cancelar").

int alert3(const char *s1, *s2, *s3, const char *b1, *b2, *b3,
      int c1, c2, c3);
   Como alert(), pero con tres botones. Devuelve 1, 2, o 3.

int file_select(const char *message, char *path, const char *ext);
   Deprecado. Use file_select_ex() en su lugar, pasando las dos constantes
   OLD_FILESEL_WIDTH y OLD_FILESEL_HEIGHT si desea que el selector de
   ficheros sea visualizado con las dimensiones del antiguo selector.

int file_select_ex(const char *message, char *path, const char *ext,
                    int size, int w, int h);
   Visualiza el selector de ficheros de Allegro, con la cadena message como
   ttulo. El parmetro path contiene el nombre del fichero inicial a
   visualizar (esto puede ser usado como el comienzo del directorio, o
   para dar un nombre por defecto a un salvar-como). La seleccin del
   usuario se devuelve alterando el buffer path, cuya longitud mxima en
   bytes est indicada por el parmetro size. Recuerde que debera tener como
   mnimo espacio para 80 carcteres (no bytes), por lo que debera reservar
   seis veces esa cantidad, para asegurarse. La lista de ficheros es filtrada
   de acuerdo con las extensiones de ficheros en ext. Pasar NULL incluye
   todos los ficheros, "PCX;BMP" incluye solamente los ficheros con
   extensiones .PCX o .BMP. Si desea controlar los ficheros por sus
   atributos, uno de los campos de la lista de extensiones puede empezar con
   una barra, seguida por un conjunto de carcteres de atributos. Cualquier
   atributo escrito solo, o con un '+' antes de l, indica que slo se
   incluyan ficheros que tengan ese atributo activo. Cualquier atributo con
   un '-' antes de l indica que hay que dejar fuera los ficheros con ese
   atributo. Los atributos son 'r' para slo lectura (read-only), 'h' para
   ocultos (hidden), 's' para archivos de sistema (system), 'd' para
   directorios (directory), y 'a' para tipo archivo (archive). Por ejemplo,
   una cadena de extension "PCX;BMP;/+r-d" mostrar solamente ficheros PCX o
   BMP que sean de slo lectura pero no los directorios. El dilogo del
   selector de ficheros ser reescalado a la anchura y altura especificadas
   y al tamao de la fuente. Si alguno de los parmetros est a cero,
   entonces la funcin escalar el dilogo a la dimensin apropiada de la
   pantalla. Devuelve cero si fue cerrada con el botn Cancelar, y distinto
   de cero si se cerr con OK.

   

int gfx_mode_select(int *card, int *w, int *h);
   Ensea el dilogo de seleccin de modo grfico de Allegro, que permite al
   usuario seleccionar el modo y tarjeta de vdeo. Almacena la seleccin en
   las tres variables, y devuelve cero si se cerr con el botn Cancelar y
   distinto de cero si se cerr con OK.

int gfx_mode_select_ex(int *card, int *w, int *h, int *color_depth);
   Versin extendida del dilogo de seleccin de modo grfico, que permite
   al usuario seleccionar tanto el nmero de colores como la resolucin y el
   controlador de vdeo. Esta versin de la funcin lee los valores
   iniciales de los parmetros cuando se activa, por lo que puede
   especificar los valores por defecto.

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);
   Si ajusta alguno de estos punteros, las funciones a las que apunten sern
   usadas por los dilogos estndar de Allegro. Esto le permite personalizar
   el `look and feel', al estilo de gui_fg_color y gui_bg_color, pero con
   mucha mayor flexibilidad.

 


=========================================================
============ 33 Detalles especficos del DOS ============
=========================================================

Drivers: JOY_TYPE_*/DOS
   La biblioteca para DOS soporta los siguientes tipos de parmetros para
   la funcin install_joystick():

   JOY_TYPE_AUTODETECT
      Intenta detectar el joystick instalado. En realidad es imposible
      distinguir entre todas las posibles configuraciones, por lo que
      esta rutina slo puede elegir el controlador de joystick estndar,
      Sidewider, GamePad Pro, o GrIP, pero usar informacin del fichero
      de configuracin si ste existe (el fichero puede ser creado usando
      la utilidad setup o llamando a la funcin save_joystick_data()), por
      lo que siempre puede usar JOY_TYPE_AUTODETECT en su cdigo y elegir
      el tipo de hardware exacto desde el programa setup.

   JOY_TYPE_NONE
      Controlador vaco para mquinas sin joystick.

   JOY_TYPE_STANDARD
      Un joystick normal de dos botones.

   JOY_TYPE_2PADS
      Modo de joystick dual (dos joysticks, cada uno con dos botones).

   JOY_TYPE_4BUTTON
      Activa los botones extras de un joystick de 4 botones.

   JOY_TYPE_6BUTTON
      Activa los botones extras de un joystick de 6 botones.

   JOY_TYPE_8BUTTON
      Activa los botones extras de un joystick de 8 botones.

   JOY_TYPE_FSPRO
      Joystick CH Flightstick Pro o compatible, que tiene cuatro botones,
      un mando de gases analgico, y un sombrero de 4 direcciones.

   JOY_TYPE_WINGEX
      Un Logitech Wingman Extreme, que debera funcionar con cualquier
      joystick compatible Thrustmaster Mk.I. Tiene soporte para cuatro
      botones y un sombrero. Esto tambin funciona con el Wingman Warrior,
      si conecta el conector de 15 pins (recuerde desconectar el conector
      de 9 pins!) y si ajusta el pequeo interruptor de adelante a la
      posicin "H" (sin embargo, no podr usar el mando de gases o el
      'spinner').

   JOY_TYPE_SIDEWINDER
      El pad digital Microsoft Sidewinder (soporta hasta cuatro mandos,
      cada uno con diez botones y un control digital de direccin).

   JOY_TYPE_SIDEWINDER_AG
      Versin alternativa de JOY_TYPE_SIDEWINDER. Pruebe con esto si su
      Sidewinder no es reconocido con JOY_TYPE_SIDEWINDER.

   JOY_TYPE_GAMEPAD_PRO
      El Gravis GamePad Pro (soporta dos mandos, cada uno con diez botones y
      un control digital de direccin).

   JOY_TYPE_GRIP
      Controlador GrIP de Gravis, usando el fichero de controlador grip.gll.

   JOY_TYPE_GRIP4
      Versin del controlador GrIP de Gravis que est restringido a moverse
      slamente a lo largo de los cuatro ejes principales.

   JOY_TYPE_SNESPAD_LPT1
   JOY_TYPE_SNESPAD_LPT2
   JOY_TYPE_SNESPAD_LPT3
      Pads SNES conectados a los puertos LPT1, LPT2, y LPT3 respectivamente.

   JOY_TYPE_PSXPAD_LPT1
   JOY_TYPE_PSXPAD_LPT2
   JOY_TYPE_PSXPAD_LPT3
      Pads PSX conectados a los puertos LPT1, LPT2, y LPT3 respectivamente.
      Mire http://www.ziplabel.com/dpadpro/index.html para obtener
      informacin sobre el cable paralelo necesario. El controlador
      automgicamente detecta qu tipos de pads PSX estn conectados de
      entre los digitales, analgicos (modo rojo o verde), NegCon, multi
      taps, pistolas de luz Namco, Jogcons (volantes con retroalimentacin
      de fuerza), y el ratn. Si el mando no es reconocido es tratado como
      un mando analgico, queriendo decir que el controlador debera
      funcionar con casi cualquier cosa. Puede conectar los mandos como
      desee, pero slo sern usados los primeros 8.

      El Dual Shock de Sony o el Jogcon de Namco se volvern a colocar ellos
      mismos en modo digital despus de no haber sido muestreados durante 5
      segundos. Esto es normal, pasa lo mismo en una Playstation, estn
      diseados para detener cualquier vibracin en caso de que la mquina
      anfitrin se cuelgue. Otros mandos multifuncin tendrn rarezas
      similares. Sin embargo, si esto le ocurre a un mando Jogcon, el botn
      para cambiar de modo ser desactivado. Para reactivarlo, tendr que
      apretar y mantener pulsados al mismo tiempo los botones Start y Select.

      El G-con45 necesita ser conectado (y apuntar) a un monitor de tipo TV
      conectado a su ordenador. La salida compuesta de vdeo de mi tarjeta
      funciona bien con sto (una Hercules Stingray 128/3D 8Mb). Los modos
      de vdeo TV tambin deberan funcionar en Mame.

   JOY_TYPE_N64PAD_LPT1
   JOY_TYPE_N64PAD_LPT2
   JOY_TYPE_N64PAD_LPT3
      Pads N64 conectados a los puertos LPT1, LPT2, y LPT3 respectivamente.
      Mire http://www.st-hans.de/N64.htm para obtener informacin
      sobre el adaptador hardware necesario. Soporta hasta cuatro mandos en
      un nico puerto paralelo. No es necesario caliblar el control
      analgico, ya que sto lo hace el mando por si mismo cuando se
      enciende. Esto significa que el stick tiene que estar centrado cuando
      el mando es inicializado. Un posible problema que la gente podra tener
      con este controlador es que es fsicamente imposible poner el stick
      analgico totalmente diagonal, pero no veo que esto pueda causar
      grandes problemas. Esto es debido a la forma del mando donde reposa la
      palanca del control analgico. Como el del Gravis Game Pad Pro, este
      controlador necesita desconectar brevemente las interrupciones de
      hardware mientras es muestreado. Esto causa un notable impacto en la
      ejecucin de mi maquina con ambos controladores, pero no hay modo de
      evitarlo. En una (muy) tosca suposicin dira que sto relentiza el
      Mame un 5%-10%.

   JOY_TYPE_DB9_LPT1
   JOY_TYPE_DB9_LPT2
   JOY_TYPE_DB9_LPT3
      Una pareja de joysticks de dos botones conectados al puerto LPT1,
      LPT2 y LPT3 respectivamente. El primer puerto es compatble con un
      controlador joy-db9 (multisistema 2 botones), y el segundo es
      compatible con la interfaz Atari del DirectPad Pro. Lea en el fichero
      de cdigo fuente (src/dos/multijoy.c) informacin de los pines.

   JOY_TYPE_TURBOGRAFIX_LPT1
   JOY_TYPE_TURBOGRAFIX_LPT2
   JOY_TYPE_TURBOGRAFIX_LPT3
      Estos controladores soportan hasta 7 joysticks, cada uno con hasta 5
      botones, conectados a los puertos LPT1, LPT2 y LPT3 respectivamente.
      Usan la interfaz TurboGraFX de Steffen Schwenke: mire
      http://www.burg-halle.de/~schwenke/parport.html para ms
      detalles sobre cmo construir esto.

   JOY_TYPE_WINGWARRIOR
      Un joystick Wingman Warrior.

   JOY_TYPE_IFSEGA_ISA
   JOY_TYPE_IFSEGA_PCI
   JOY_TYPE_IFSEGA_PCI_FAST
      Controlador para las tarjetas con interfaz de joystick IF-SEGA, de
      la compana IO-DATA (stas existen en variantes PCI, PCI2 e ISA).

Drivers: GFX_*/DOS
   La librera para DOS soporta los siguientes parmetros de tarjeta para
   la funcin set_gfx_mode():

   GFX_TEXT
      Volver al modo texto.

   GFX_AUTODETECT
      Deja que Allegro escoja un driver grfico apropiado.

   GFX_AUTODETECT_FULLSCREEN
      Autodetecta el driver grfico, pero slo usar drivers a pantalla
      completa, fallando si no estn disponibles en la plataforma actual.

   GFX_AUTODETECT_WINDOWED
      Igual que el anterior, pero slo con drivers en ventana. Esto siempre
      fallar bajo DOS.

   GFX_SAFE
      Controlador especial para cuando quiere establecer un modo grfico
      seguro y no le importa realmente en qu resolucin o profundidad de
      color. Mire para ms detalles la documentacin de set_gfx_mode().

   GFX_VGA
      El modo 13h estndar de 256 colores de la VGA, usando el controlador
      GFX_VGA. Este es normalmente 320x200, que le permitir trabajar con
      cualquier VGA pero no soporta pantallas virtuales grandes ni scroll
      por hardware. Allegro permite tambin varias variantes modificadas de
      este modo que permiten scroll, miden 320x100 (con una pantalla virtual
      de 200 pixels de altura), 160x120 (con una pantalla virtual de 409
      pixels de altura), 256x256 (sin scroll), y 80x80 (con una pantalla
      virtual de 819 pixels de altura).

   GFX_MODEX
      El Modo-X funcionar en cualquier tarjeta VGA, y permite un rango de
      resoluciones modificadas de 256 colores.

      Resoluciones estables del modo-X:

         Razn de aspecto cuadrado: 320x240

         Razn de aspecto oblicuo: 256x224, 256x240, 320x200, 320x400,
                                   320x480, 320x600, 360x200, 360x240,
                                   360x360, 360x400, 360x480

         Estos han funcionado en cada tarjeta/monitor que he probado.

      Resoluciones de modo-X inestables:

         Razn de aspecto cuadrado: 360x270, 376x282, 400x300

         Razn de aspecto oblicuo: 256x200, 256x256, 320x350, 360x600,
                                   376x308, 376x564, 400x150, 400x600

         Estos slo funcionan en algunos monitores. Funcionaron bien en mi
         vieja mquina, pero no se llevan bien con mi nuevo monitor. Si est
         preocupado por la posibilidad de daar su monitor usando estos
         modos, no lo est. Por supuesto no estoy dando ninguna garanta al
         respecto, y si su hardware explota es una pena, pero no creo que
         este tipo de ajustes puedan hacer dao alguno. De la documentacin
         del programa TWEAK de Robert Schmidt:

            "Hace tiempo, poner valores o combinaciones ilegales o no
            soportadas en los registros de la tarjeta de vdeo poda ser
            peligroso para su salud y para su monitor. *Nunca* he declarado
            que esto no pueda pasar si usa TWEAK, pero estoy muy seguro de
            que esto nunca pasar. Nunca he odo que usar TWEAK o cambiar
            manualmente los registros de la VGA hayan ocasionado dao
            alguno."

      La mayora de las funciones de dibujo en el modo-X son ms lentas que
      en el modo 13h, debido a la complejidad de la organizacin planar del
      bitmap, pero los rellenos de reas slidas y los blits alineados al
      plano de una parte de la memoria de vdeo a otra pueden ser
      significativamente ms rpidos, particularmente en hardware antiguo.
      El modo-x accede a las 256k totales de la RAM de la VGA, por lo que el
      scroll por hardware y el intercambio de pginas es posible, y es
      posible partir la pantalla para mover la parte superior y tener un
      indicador de estado fijo en la parte inferior.

   GFX_VESA1
      Usa el controlador VESA 1.x.

   GFX_VESA2B
      Usa el controlador VBE 2.0 con bancos.

   GFX_VESA2L
      Usa el controlador VBE 2.0 con framebuffer lineal.

   GFX_VESA3
      Usa el controlador VBE 3.0. Este es el nico controlador VESA que
      soporta la funcin request_refresh_rate().

      Los modos VESA estndares son 640x480, 800x600, y 1024x768. Estos
      deberan funcionar con cualquier tarjeta SVGA: si no lo hacen, consiga
      una copia del Scitech Display Doctor y mire si se soluciona el
      problema. Las profundidades de color disponibles dependen de su
      hardware. La mayora de las tarjetas soportan resoluciones de 15 y 16
      bits, pero si es posible se recomendara implementar ambas (no es tan
      difcil...) en caso de que una no est disponible. Algunas tarjetas
      permiten color verdadero de 24 y 32 bits, en cuyo caso la eleccin
      es entre 24 (salvar memoria) o 32 (va ms rpido), pero algunas
      tarjetas antiguas no tienen modos de 32 bits y algunas nuevas no
      soportan resoluciones de 24 bits. Use el programa de test vesainfo
      para saber qu modos puede visualizar con su controlador VESA.

      Muchas tarjetas tambin soportan 640x400, 1280,1024 y 1600x1200, pero
      estos modos no siempre estn disponibles, por ejemplo las tarjetas S3
      no tienen modo 640x400. Otras resoluciones raras pueden estar
      disponibles, ej: algunas tarjetas Tseng tienen un modo 640x350, y la
      Advance Logic tiene un modo de 512x512.

      El SciTech Display Doctor provee varios modos de baja resolucin en
      los que puede hacer scroll en un rango diferente de profundidades de
      color (320x200, 320x240, 320x400, 320x480, 360x200, 360x240, 360x400,
      y 360x480 funcionan en mi ET4000 a 8, 15 o 16 bits por pixel). Estos
      modos son fenomenales, permitindle hacer scroll o intercambio de
      pginas sin la complejidad del modo-X, pero desafortunadamente no son
      un estndar, por lo que necesitar el Display Doctor para poder
      usarlos.

   GFX_VBEAF
      VBE/AF es un superconjunto del estndar VBE 2.0, que trae un API para
      acceder a caractersticas de aceleracin por hardware. Los
      controladores VBE/AF actualmente slo estn disponibles desde el
      proyecto FreeBE/AF o como una parte del pack del SciTech Display
      Doctor, pero puede proporcionar grandes mejoras en la velocidad si se
      usa con el hardware adecuado. Para ver una discusin detallada sobre
      la aceleracin por hardware, lea la documentacin sobre la variable
      gfx_capabilities.

      Puede usar el programa test afinfo para comprobar si tiene un
      controlador VBE/AF, y para ver qu resoluciones soporta.

      Los controladores VBE/AF de SciTech requieren que el acceso con
      nearptr est activado, por lo que cualquier puntero errneo puede
      bloquear su mquina cuando estos controladores estn en uso. Esto
      significa que puede ser buena idea usar VESA mientras depura su
      programa, y activar VBE/AF slo cuando el cdigo funcione
      correctamente. Los controladores FreeBE/AF no tienen este problema.
   
   GFX_XTENDED
      Un modo 640X400 con memoria plana como est descrito por Mark Feldman
      en PCGPE. Usa VESA para seleccionar un modo SVGA (por lo tanto, slo
      funcionar en tarjetas que soporten una resolucin VESA 640X400), y
      luego activa la memoria plana como si se fuese a utilizar el modo-x.
      Esto permite que la pantalla entera pueda ser direccionada sin
      necesidad de utilizar conmutacin de bancos, aunque el scroll por
      hardware y el intercambio de pginas no sern posibles. Este driver
      nunca ser autodetectado (en su lugar el modo VESA 640X400 normal ser
      el seleccionado), por lo tanto si desea utilizarlo, deber pasar
      GFX_EXTENDED explcitamente a set_gfx_mode().

Drivers: DIGI_*/DOS
   Las funciones DOS soportan las siguientes tarjetas de sonido digitales:

      DIGI_AUTODETECT      - permite que Allegro elija un driver de sonido
                             digital
      DIGI_NONE            - sin sonido digital
      DIGI_SB              - Sound Blaster (autodeteccin)
      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 dma autoinicializada)
      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
   Las funciones DOS soportan las siguientes tarjetas de sonido MIDI:

      MIDI_AUTODETECT      - permite que Allegro elija un driver de sonido
                             MIDI
      MIDI_NONE            - sin sonido MIDI
      MIDI_ADLIB           - Adlib o sintetizador FM SB (autodeteccin)
      MIDI_OPL2            - sintetizador OPL2 (mono, usado en Adlib y SB)
      MIDI_2XOPL2          - sintetizadores duales OPL2 (stereo, usado en SB
                             Pro-I)
      MIDI_OPL3            - sintetizador OPL3 (stereo, SB Pro-II y
                             superiores)
      MIDI_SB_OUT          - interfaz MIDI SB
      MIDI_MPU             - interfaz MIDI MPU-401
      MIDI_DIGMID          - reproductor por software de tablas de ondas
                             basado en samples
      MIDI_AWE32           - AWE32 (chip EMU8000)

void split_modex_screen(int line);
   Esta funcin slo est disponible en modo-X. Permite la divisin de la
   pantalla VGA en dos partes por una lnea especifica. En la mitad superior
   de la pantalla puede hacer scroll a cualquier punto de la memoria de video
   mediante la funcin scroll_screen(), pero la parte inferior ser siempre
   fija y mostrar el contenido de la posicin (0, 0) del bitmap de pantalla
   (screen). Tras dividir la pantalla, normalemente querr hacer un scroll de
   forma que la parte superior muestre una zona ms baja de la memoria de
   video y despus crear dos sub-bitmaps para acceder a ambas secciones (en
   examples/exscroll.c tiene una demostracin de cmo se puede hacer esto).
   Para desactivar la divisin, llame a split_modex_screen(0).

extern int i_love_bill;
   Cuando se ejecuta en entorno DOS puro, el temporizador reprograma
   dinmicamente el reloj para generar interrupciones en los momentos
   exactos, lo que confiere una exactitud extremadamente alta.
   Desafortunadamente, esta velocidad constante no funciona correctamente en
   la mayora de sistemas multitarea (sobre todo bajo Windows), por lo tanto,
   existe un modo alternativo que bloquea la interrupcin del temporizador
   por hardware a una velocidad de 200 ticks por segundo. Esto, reduce la
   fiabilidad del temporizador (por ejemplo, rest() redondear el tiempo de
   espera al 5 milisegundo ms cercano al tiempo especificado), e impide al
   simulador de retrazo vertical su funcionamiento, pero como punto positivo,
   permite que los programas de Allegro funcionen bajo Windows. Esta variable
   es inicializada por allegro_init() si se detecta la presencia de un
   sistema operativo multitarea y adems se activa el modo de temporizador de
   razn fija.



============================================================
============ 34 Detalles especficos de Windows ============
============================================================

Un programa para Windows que use Allegro slo tiene que inclur uno o ms
ficheros del rbol include/allegro, o allegro.h; no obstante, si tambin
necesita llamar directamente a funciones no portables del API Win32, deber
inclur el fichero de cabecera especfico de Windows winalleg.h justo tras
allegro.h, y antes de cualquier otro fichero de cabecera del API Win32. Por
defecto winalleg.h incluye el fichero de cabecera principal windows.h del
API Win32. Si por el contrario desea usar la interfaz C++ del API Win32 (es
decir, las Microsoft Foundation Classes), defina el smbolo de preprocesador
ALLEGRO_AND_MFC antes de inclur cualquier fichero de cabecera de Allegro
para que afxwin.h sea includo. Tenga en cuenta que en este ltimo caso, las
macros de depuracin ASSERT() y TRACE() sern renombradas a AL_ASSERT() y
AL_TRACE() respectivamente.

Las aplicaciones GUI de Windows empiezan con un punto de entrada WinMain(),
en vez del punto de entrada estndar main(). Allegro est configurado para
crear aplicaciones GUI por defecto y hacer unos trucos de magia para que la
funcin regular main() funcione sin problemas, pero para esto necesita que
escriba END_OF_MAIN() justo tras su funcin main(). Si no quiere hacer esto,
puede inclur winalleg.h y escribir una funcin WinMain(). Note que estos
trucos de magia pueden tener conflictos con algunos programas que hagan
llamadas directas al API Win32; para estos programas, es imprescindible la
funcin WinMain() y que los trucos de magia sean desactivados definiendo el
smbolo de preprocesador ALLEGRO_NO_MAGIC_MAIN antes de inclur los ficheros
de cabecera de Allegro.

Si quiere crear una aplicacin de consola con Allegro, debe definir el
smbolo de preprocesador USE_CONSOLE antes de incluir los ficheros de
cabecera de Allegro; esto indicar a la librera que use caractersticas del
modo consola y que desactive el procesado especial de la funcin main()
descrito arriba.

Cuando crea la ventana principal, Allegro busca en el ejecutable un recurso
de icono nombrado "allegro_icon". Si est presente, Allegro lo cargar y
usar automticamente como icono de aplicacin. En caso contrario, Allegro
usar el icono por defecto IDI_APPLICATION.

DirectX requiere que los bitmaps de vdeo y sistema estn bloqueados en
memoria (locked) antes de que pueda dibujar en ellos. Esto se har
automticamente, pero podr conseguir habitualmente una ejecucon ms ptima
hacindolo usted mismo: mire la funcin acquire_bitmap() para ms detalles.

Debido a un gran descuido en el diseo de DirectX, no hay manera de
preservar los contenidos de la memoria de vdeo cuando el usuario cambia
a otra ventana desde su programa. Necesita estar preparado para el hecho
de que el contenido de su pantalla, y el contenido de cualquier bitmap en
memoria de vdeo, puede ser destruido en cualquier momento. Puede usar la
funcin set_display_switch_callback() para arreglrselas cuando ocurra esto.

En la plataforma Windows, los nicos valores de retorno de
desktop_color_depth() son 8, 16, 24 y 32. Esto significa que no puede
diferenciar escritorios de 15 o 16 bits, dado que ambos se muestran como
escritorios de 16 bits. Lea abajo las consecuencias que tiene esto para los
drivers en ventana y modos overlay.

Drivers: GFX_*/Windows
   La biblioteca para Windows soporta los siguientes parmetros de tarjeta
   para la funcin set_gfx_mode():

   GFX_TEXT
      Esto cierra el modo grfico abierto previamente con set_gfx_mode.

   GFX_AUTODETECT
      Deja que Allegro escoja un controlador grfico apropiado.

   GFX_AUTODETECT_FULLSCREEN
      Autodetecta el driver grfico, pero slo usar drivers a pantalla
      completa, fallando si no estn disponibles en la plataforma actual.

   GFX_AUTODETECT_WINDOWED
      Igual que el anterior, pero slo con drivers en ventana. Esto siempre
      fallar bajo DOS.

   GFX_SAFE
      Controlador especial para cuando quiere establecer un modo grfico
      seguro y no le importa realmente en qu resolucin o profundidad de
      color. Mire para ms detalles la documentacin de set_gfx_mode().

   GFX_DIRECTX
      Igual que GFX_DIRECTX_ACCEL.

   GFX_DIRECTX_ACCEL
      El controlador normal DirectX a pantalla completa, corriendo con
      aceleracin por hardware.

   GFX_DIRECTX_SOFT
      Controlador a pantalla completa DirectX que slo usa dibujado por
      software, ignorando las caractersticas de aceleracin por hardware.

   GFX_DIRECTX_SAFE
      Controlador a pantalla completa DirectX simplificado que no soporta
      ninguna aceleracin por hardware, bitmaps de vdeo o sistema, etc.

   GFX_DIRECTX_WIN
      El driver en ventana de DirectX, usando conversin de color cuando la
      profindidad de color no sea igual a la del escritorio de Windows. La
      conversin de color es mucho ms lenta que dibujar directamente y no
      est soportada en escritorios con una profundidad de color de 15 o
      16 bits por pixel. Esta ltima limitacin existe para resolver la
      limitacin de desktop_color_depth() (lea ms arriba) y permite
      seleccionar un modo de dibujado sin conversiones de forma segura en
      escritorios que dicen ser de 16 bits:

         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) {
                  /* modo dibujado directo en 640x480 no soportado */
                  goto Error;
               }
            }
            /* ok, estamos en un modo de dibujado directo */
         }


   GFX_DIRECTX_OVL
      Controlador overlay de DirectX. Usa caractersticas especiales de
      hardware para ejecutar su programa en modo ventana: no funciona con
      todo el hardware, pero el rendimiento es excelente en las tarjetas que
      son capaces de ello. Requiere que la profundidad de color sea igual a
      la del escritorio de Windows. En vista de la limitacin de
      desktop_color_depth() (lea ms arriba), la forma segura de seleccionar
      el driver overlay en escritorios que dicen ser de 16 bits es:

         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) {
                  /* driver overlay en 640x480 no soportado */
                  goto Error;
               }
            }
            /* ok, estamos en modo overlay a 640x480 */
         }


   GFX_GDI
      Controlador GDI en modo ventana. Es extremadamente ineficiente, pero
      est garantizado que funcionar con cualquier hardware, as que puede
      ser til para situaciones en las que quiere ejecutar su programa en
      una ventana y no le importe el rendimiento. Tenga en cuenta que este
      driver usa una emulacin hardware del cursor del ratn para acelerar
      las operaciones bsicas de ste (como operaciones GUI).

Drivers: DIGI_*/Windows
   Las funciones de sonido para Windows soportan las siguientes tarjetas
de sonido digitales:

      DIGI_AUTODETECT      - Allegro elige un controlador de sonido digital.
      DIGI_NONE            - sin sonido digital.
      DIGI_DIRECTX(n)      - usa el dispositivo DirectSound #n (siendo 'n'
                             mayor o igual que cero) con mezclado directo
      DIGI_DIRECTAMX(n)    - usa el dispositivo DirectSound #n (siendo 'n'
                             mayor o igual que cero) con el mezclador de
                             Allegro
      DIGI_WAVOUTID(n)     - alta (n=0) o baja (n=1) calidad del dispositivo
                             WaveOut

Drivers: MIDI_*/Windows
   Las funciones de sonido de Windows soportan las siguientes tarjetas de
sonido MIDI:

      MIDI_AUTODETECT      - Allegro escoge un controlador de sonido MIDI.
      MIDI_NONE            - sin sonido MIDI
      MIDI_WIN32MAPPER     - usa el mapeador MIDI win32
      MIDI_WIN32(n)        - usa el dispositivo win32 #n (siendo 'n' mayor o
                             igual que cero)
      MIDI_DIGMID          - reproductor wavetable basado en samples


Las siguientes funciones proveen una interfaz especfica de la plataforma
para integrar Allegro sin problemas con cualquier programa Win32 de propsito
general. Para usar estas rutinas, debe incluir winalleg.h tras otros ficheros
de cabecera de Allegro.

HWND win_get_window(void);
   Recupera el handle de la ventana usada por Allegro. Note que Allegro usa
   una ventana incluso si no ha activado ningn modo grfico, a no ser que
   haya instalado el driver de sistema neutral (SYSTEM_NONE).

void win_set_window(HWND wnd);
   Hace que Allegro use una ventana creada por el usuario. Esta funcin debe
   ser llamada *antes* de iniciar la librera con allegro_init() o
   instalando el driver de sistema con autodeteccin (SYSTEM_AUTODETECT). Le
   permite enganchar Allegro a una ventana ya existente y evita que la
   librera cre la suya, dejndole el control total de la ventana; en
   particular, usted ser responsable de manejar los eventos como siempre
   (Allegro monitorizar automticamente algunos de ellos, pero no los
   filtrar). Puede usar cualquier componente de la librera (ratn, teclado,
   sonido, temporizacin, etc) excepto el subsistema grfico.

void win_set_wnd_create_proc(HWND (*proc)(WNDPROC));
   Hace que Allegro use una funcin definida por el usuario para crear su
   ventana. Esta funcin debe ser llamada *antes* de iniciar la librera
   con allegro_init() o instalando el driver de sistema con autodeteccin
   (SYSTEM_AUTODETECT). Le permite personalizar la ventana de Allegro pero
   slo en su creacin: a diferencia de win_set_window(), no tendr control
   sobre la ventana una vez sea creada (en particular, no ser responsable
   de procesar los eventos). A la funcin registrada se le pasar un
   procedimiento de ventana (objeto WNDPROC) que debe hacer el procedimiento
   de la nueva ventana y debe devolver el hadle a la nueva ventana. Puede
   usar la librera sin restricciones de la forma habitual.

HDC win_get_dc(BITMAP *bmp);
   Recupera el handle del dispositivo de contexto del vdeo DirectX o un
   bitmap de sistema.

void win_release_dc(BITMAP *bmp, HDC dc);
   Libera el handle del dispositivo de contexto del bitmap que fue
   previamente recuperado por win_get_dc().


Estas rutinas GDI son algo muy especfico de la plataforma, para permitir
dibujar mapas de bits en memoria de Allegro sobre un contexto de un
dispositivo de Windows. Cuando usted quiera usarlas, necesitar instalar el
driver de sistema neutral (SYSTEM_NONE) si llama a install_allegro() o
enganchar Allegro a una ventana externa con win_set_window() si llama a
allegro_init().

Existen dos formas de dibujar sus mapas de bits de Allegro sobre la GDI de
Windows. Cuando usted est usando mapas de bits estticos (por ejemplo unos
pocos dibujos cargados de un archivo de datos), usted puede convertirlos a
DDB (bitmaps dependientes del dispositivo) con convert_bitmap_to_hbitmap() y
luego usar simplemente el BitBlt() de Win32 para dibujarlos.

Cuando usted usa mapas de bits dinmicos (por ejemplo elementos que
reaccionan segn la entrada del usuario), es mejor usar las funciones
set_pallette_to_hdc y blit_to_hdc(), que funcionan con DIB (mapas de bits
independientes del dispositivo).

Existen adems funciones para hacer blit desde un contexto de dispositivo en
un BITMAP de Allegro, as que usted puede realizar cosas como captura la
pantalla.

Todas las funciones de dibujo y conversin usan la paleta actual como una
tabla de conversin de colores. Usted puede alterar la paleta actual con las
funciones set_palette_to_hdc() o select_palette(). Advertencia: cuando la
paleta de colores del sistema es cambiada explcitamente, (por ejemplo, por
otra aplicacin) la paleta actual de Allegro no es actualizada con ello!

Para usar estas rutinas debe incluir winalleg.h tras los dems ficheros de
cabecera de Allegro.

void set_gdi_color_format(void);
   Le dice a Allegro que use el mapa de colores del GDI para imgenes de
   color verdadero. Esto es opcional, pero har que las conversiones
   funcionen ms rpido. Si usted va a llamar a sta funcin, debera hacerlo
   despus de iniciar Allegro y ntes de crear grficos.

void set_palette_to_hdc(HDC dc, PALETTE pal);
   Selecciona y realiza una paleta de Allegro sobre el contexto de
   dispositivo especfico.

HPALETTE convert_palette_to_hpalette(PALETTE pal);
   Convierte una paleta de Allegro a una paleta de Windows y devuelve su
   manejador. Usted debera llamar a DeleteObject() cuando no la necesite
   ms.

void convert_hpalette_to_palette(HPALETTE hpal, PALETTE pal);
   Convierte una paleta de Windows en una paleta de Allegro.

HBITMAP convert_bitmap_to_hbitmap(BITMAP *bitmap);
   Convierte un mapa de bits de memoria en un DDB de Windows y devuelve su
   manejador. Este mapa de bits usa su propia memoria, as que puede destruir
   el original sin afectar al convertido. Usted debera llamar DeleteObject()
   cuando no necesite ms este mapa de bits.

BITMAP *convert_hbitmap_to_bitmap(HBITMAP bitmap);
   Crea un bitmap de Allegro en memoria desde un DDB de Windows.

void draw_to_hdc(HDC dc, BITMAP *bitmap, int x, int y);
   Dibuja todo un bitmap de Allegro en un contexto de dispositivo de Windows,
   usando los mismos parmetros que la funcin draw_sprite().

void blit_to_hdc(BITMAP *bitmap, HDC dc, int sx, sy, dx, dy, w, h);
   Realiza un blit de un mapa de bits de Allegro a un contexto de dispositivo
   de Windows, usando los mismos parmetros que la funcin blit().

void stretch_blit_to_hdc(BITMAP *bitmap, HDC dc, int sx, sy, sw, sh,
                                                 int dx, dy, dw, dh);
   Realiza un blit de un mapa de bits de Allegro a un contexto de dispositivo
   de Windows, usando los mismos parmetros que la funcin stretch_blit().

void blit_from_hdc(HDC hdc, BITMAP *bitmap, int sx, sy, dx, dy, w, h);
   Realiza un blit de un mapa de bits de Allegro a un contexto de dispositivo
   de Windows, usando los mismos parmetros que la funcin blit(). Vea
   stretch_blit_from_hdc() para ms detalles.

void stretch_blit_from_hdc(HDC hcd, BITMAP *bitmap, int sx, sy, sw, sh,
                                                    int dx, dy, dw, dh);
   Realiza un blit de un mapa de bits de Allegro a un contexto de dispositivo
   de Windows, usando los mismos parmetros que la funcin stretch_blit().
   Usa la paleta actual de Allegro y realiza una conversin a sta paleta,
   sin importar la paleta DC actual. As que si usted est realizando un blit
   desde el modo de 8 bits, debera primero actualizar la paleta DC con la
   funcin set_palette_to_hdc().



=========================================================
============ 35 Detalles especficos de Unix ============
=========================================================

Para poder localizar cosas como los ficheros de configuracin o traduccin,
Allegro necesita conocer el path de su ejecutable. Ya que no hay forma
estndar para hacer eso, necesita capturar una copia de sus parmetros
argv[], cosa que hace con trucos de preprocesador. Desafortunadamente no
puede conseguirlo sin un poco de ayuda por su parte, por lo que tendr que
escribir END_OF_MAIN() justo tras su funcin main(). Muy fcil, realmente, y
si se olvida de hacerlo, obtendr un agradable error de enlazado sobre una
funcin inexistente _mangled_main que se lo recordar :-)

Drivers: GFX_*/Linux
   Cuando use Linux en modo consola, Allegro soporta los siguientes
   parmetros de tarjeta para la funcin set_gfx_mode():

   GFX_TEXT
      Vuelve al modo texto.

   GFX_AUTODETECT
      Permite que Allegro elija un controlador grfico apropiado.

   GFX_AUTODETECT_FULLSCREEN
      Autodetecta el driver grfico, pero slo usar drivers a pantalla
      completa, fallando si no estn disponibles en la plataforma actual.

   GFX_AUTODETECT_WINDOWED
      Igual que el anterior, pero slo con drivers en ventana. Esto siempre
      fallar bajo DOS.

   GFX_SAFE
      Controlador especial para cuando quiere establecer un modo grfico
      seguro y no le importa realmente en qu resolucin o profundidad de
      color. Mire para ms detalles la documentacin de set_gfx_mode().

   GFX_FBCON
      Usa el dispositivo framebuffer (ej: dev/fb0). Esto requiere que tenga
      soporte para framebuffer compilado en su ncleo, y que su hardware
      est correctamente configurado. Actualmente es el nico controlador en
      modo consola que funciona sin permisos de superusuario, a no ser que
      est usando una versin de desarrollo de SVGAlib.

   GFX_VBEAF
      Usa el controlador VBE/AF (vbead.drv), asumiendo que ha instalado uno
      que funcione bajo Linux (actualmente solo dos de los controladores del
      proyecto FreeBE/AF son capaces de hacerlo: ni idea sobre los de
      SciTech). VBE/AF requiere permisos de superusuario, pero es por ahora
      el nico controlador para Linux que soporta aceleracin de grficos
      por hardware.

   GFX_SVGALIB
      Usa la librera SVGAlib para mostrar grficos. Esto requiere permisos
      de superusuario si su versin de SVGAlib los requiere.

   GFX_VGA
   GFX_MODEX
      Usa acceso directo al hardware para ajustar resoluciones VGA estndar
      o modo-X, soportando los mismos modos que las versiones DOS de estos
      controladores. Requiere permisos de superusuario.

Drivers: GFX_*/X
   Cuando est bajo X, Allegro soporta los siguientes parmetros de tarjeta
   para la funcin set_gfx_mode():

   GFX_TEXT
      Esto cierra el modo grfico abierto previamente con set_gfx_mode.

   GFX_AUTODETECT
      Permite que Allegro elija un controlador grfico apropiado.

   GFX_AUTODETECT_FULLSCREEN
      Autodetecta el driver grfico, pero slo usar drivers a pantalla
      completa, fallando si no estn disponibles en la plataforma actual.

   GFX_AUTODETECT_WINDOWED
      Igual que el anterior, pero slo con drivers en ventana. Esto siempre
      fallar bajo DOS.

   GFX_SAFE
      Controlador especial para cuando quiere establecer un modo grfico
      seguro y no le importa realmente en qu resolucin o profundidad de
      color. Mire para ms detalles la documentacin de set_gfx_mode().

   GFX_XWINDOWS
      El controlador grfico X estndar. Esto debera funcionar en cualquier
      sistema Unix, y puede operar remotamente. No requiere permisos de
      superususario.

   GFX_XWINDOWS_FULLSCREEN
      Igual que el anterior, pero mientras GFX_XWINDOWS se ejecuta en una
      ventana, este usar la extensin XF86VidMode para ejecutarse a pantalla
      completa incluso sin permisos de superusuario. Seguir usando el
      protocolo X estndar, as que espere obtener el mismo bajo rendimiento
      que con el driver en ventana.

   GFX_XDGA
      Usa la extensin DGA 1.0 de XFree86 para escribir directamente en la
      superficie de vdeo. DGA es normalmente ms rpido que el modo X
      estndar, pero no produce programas en ventana que se comporten
      adecuadamente, y no funcionar remotamente. Este controlador requiere
      permisos de superusuario.

   GFX_XDGA_FULLSCREEN
      Como GFX_XDGA, pero adems cambia la resolucin de la pantalla para
      que se ejecute en pantalla completa. Este controlador requiere
      permisos de superususario.

   GFX_XDGA2
      Usa la nueva extensin DGA 2.0 de XFree86 4.0.x. Esta funcionar en
      pantalla completa, y soportar aceleracin por hardware si est
      disponible. El controlador requiere premisos de superusuario.

   GFX_XDGA2_SOFT
      Igual que GFX_XDGA2, pero desactiva la aceleracin por hardware.
      Este controlador requiere permisos de superusuario.

Drivers: DIGI_*/Unix
   Las funciones de sonido Unix soportan las siguientes tarjetas de sonido
   digital:

      DIGI_AUTODETECT      - permite que Allegro elija el controlador de
                             sonido
      DIGI_NONE            - sin sonido digital
      DIGI_OSS             - Open Sound System
      DIGI_ESD             - Enlightened Sound Daemon
      DIGI_ALSA            - controlador de sonido ALSA

Drivers: MIDI_*/Unix
   Las funciones de sonido Unix soportan las siguientes tarjetas MIDI:

      MIDI_AUTODETECT      - permite que Allegro elija un controlador de
                             sonido MIDI
      MIDI_NONE            - sin sonido MIDI
      MIDI_OSS             - Open Sound System
      MIDI_DIGMID          - reproductor software basado en samples
      MIDI_ALSA            - controlador RawMIDI ALSA




=========================================================
============ 36 Detalles especficos de BeOS ============
=========================================================

Drivers: GFX_*/BeOS
   Allegro para BeOS soporta los siguientes parmetros para la funcin
   set_gfx_mode():

   GFX_TEXT
      Esto cierra el modo grfico abierto previamente con set_gfx_mode.

   GFX_AUTODETECT
      Permite que Allegro elija un controlador grfico apropiado.

   GFX_AUTODETECT_FULLSCREEN
      Autodetecta el driver grfico, pero slo usar drivers a pantalla
      completa, fallando si no estn disponibles en la plataforma actual.

   GFX_AUTODETECT_WINDOWED
      Igual que el anterior, pero slo con drivers en ventana. Esto siempre
      fallar bajo DOS.

   GFX_SAFE
      Controlador especial para cuando quiere establecer un modo grfico
      seguro y no le importa realmente en qu resolucin o profundidad de
      color. Mire para ms detalles la documentacin de set_gfx_mode().

   GFX_BEOS_FULLSCREEN
      Pantalla completa en modo exclusivo. Soporta resoluciones iguales o
      mayores que 640x480, y usa aceleracin por hardware si est
      disponible.

   GFX_BEOS_FULLSCREEN_SAFE
      Igual que GFX_FULLSCREEN, pero desactiva la aceleracin.

   GFX_BEOS_WINDOWED
      Modo rpido en ventana usando la clase BDirectWindow. No todas las
      tarjetas grficas soportan esto.

Drivers: DIGI_*/BeOS
   Las funciones de sonido BeOS soportan las siguientes tarjetas de sonido
   digital:

      DIGI_AUTODETECT      - permite que Allegro elija el controlador de
                             sonido
      DIGI_NONE            - sin sonido digital
      DIGI_BEOS            - salida digital BeOS

Drivers: MIDI_*/BeOS
   Las funciones de sonido BeOS soportan las siguientes tarjetas MIDI:

      MIDI_AUTODETECT      - permite que Allegro elija el controlador de
                             sonido MIDI
      MIDI_NONE            - sin sonido MIDI
      MIDI_BEOS            - salida MIDI BeOS
      MIDI_DIGMID          - reproductor software basado en samples




========================================================
============ 37 Detalles especficos de QNX ============
========================================================

Drivers: GFX_*/QNX
   Allegro para QNX soporta los siguientes parmetros card para la funcin
   set_gfx_mode():

   GFX_TEXT
      Esto cierra el modo grfico abierto previamente con set_gfx_mode.

   GFX_AUTODETECT
      Permite que Allegro elija un controlador grfico apropiado.

   GFX_AUTODETECT_FULLSCREEN
      Autodetecta el driver grfico, pero slo usar drivers a pantalla
      completa, fallando si no estn disponibles en la plataforma actual.

   GFX_AUTODETECT_WINDOWED
      Igual que el anterior, pero slo con drivers en ventana.

   GFX_SAFE
      Controlador especial para cuando quiere establecer un modo grfico
      seguro y no le importa realmente en qu resolucin o profundidad de
      color. Mire para ms detalles la documentacin de set_gfx_mode().

   GFX_PHOTON_DIRECT
      Modo exclusivo a pantalla completa a travs de Photon.

   GFX_PHOTON
      Modo ventana en una ventana Photon.

Drivers: DIGI_*/QNX
   Las funciones de sonido QNX soportan las siguientes tarjetas de sonido
   digital:

      DIGI_AUTODETECT      - permite que Allegro elija el controlador de
                             sonido
      DIGI_NONE            - sin sonido digital
      DIGI_ALSA            - controlador de sonido ALSA

Drivers: MIDI_*/QNX
   Las funciones de sonido QNX soportan las siguientes tarjetas MIDI:

      MIDI_AUTODETECT      - permite que Allegro elija el controlador de
                             sonido MIDI
      MIDI_NONE            - sin sonido MIDI
      MIDI_ALSA            - controlador RawMIDI ALSA
      MIDI_DIGMID          - reproductor software basado en samples


Las siguientes funciones proveen una interfaz especfica de la plataforma
para integrar Allegro con programas QNX de propsito general. Para usar estas
rutinas, debe incluir qnxalleg.h tras los otros ficheros de cabecera de
Allegro.

PtWidget_t qnx_get_window(void);
   Recupera el handle de la ventana usada por Allegro. Note que Allegro usa
   una ventana incluso si no ha activado ningn modo grfico, a no ser que
   haya instalado el driver de sistema neutral (SYSTEM_NONE).



==========================================================
============ 38 Diferencias entre plataformas ============
==========================================================

Aqu tiene un rpido resumen de las cosas que pueden causar problemas cuando
mueva su cdigo de una plataforma a otra (puede encontrar una versin
detallada de esto en la seccin docs de la pgina web de Allegro).

Las versiones Windows y Unix requieren que escriba END_OF_MAIN() tras su
funcin main(), lo que transforma mgicamente su main() de estilo ANSI C en
un WinMain() de estilo Windows, y permite que el cdigo Unix obtenga una
copia de sus parmetros argv[].

En muchas plataformas Allegro funcionar lentamente si espera que bloquee
automticamente los bitmaps cuando dibuje sobre ellos. Para mejorar el
rendimiento, necesita llamar usted mismo acquire_bitmap() y
release_bitmap(), e intentar minimizar el nmero de bloqueos.

La versin Windows puede perder el contenido de la memoria de vdeo si el
usuario cambia de tarea a otro programa, por lo que deber tratar eso.

Ninguna de las plataformas actuales necesitan input polling, pero es posible
que esto sea necesario en el futuro, por lo que si quiere asegurar al 100% la
portabilidad de su programa, debera llamar poll_mouse() y poll_keyboard() en
los lugares apropiados.

Allegro define un nmero estndar de macros que pueden ser usadas para
verificar los atributos de la plataforma actual, o para aislarle de algunas
diferencias entre sistemas:

ALLEGRO_PLATFORM_STR
   Cadena de texto que contiene el nombre de la plataforma actual.

ALLEGRO_DOS
ALLEGRO_DJGPP
ALLEGRO_WATCOM
ALLEGRO_WINDOWS
ALLEGRO_MSVC
ALLEGRO_MINGW32
ALLEGRO_BCC32
ALLEGRO_UNIX
ALLEGRO_LINUX
ALLEGRO_BEOS
ALLEGRO_QNX
ALLEGRO_GCC
   Definidos si est compilando en el sistema relevante. A menudo sern
   aplicables varias, ej: DOS+Watcom, o Windows+GCC+MinGW32.

ALLEGRO_I386
ALLEGRO_BIG_ENDIAN
ALLEGRO_LITTLE_ENDIAN
   Definidos si est compilando para el procesador del tipo relevante.

ALLEGRO_VRAM_SINGLE_SURFACE
   Definido si la pantalla es una sola superficie grande partida en mltiples
   sub-bitmaps de vdeo (ej: DOS), en vez de cada bitmap sea una entidad
   totalmente nica (ej. Windows).

ALLEGRO_CONSOLE_OK
   Definido cuando no est en modo grfico, y hay una consola en modo texto a
   la cual puede mandar mensajes con printf(), salida estndar que puede ser
   capturada y redirigida por el usuario incluso cuando est en modo grfico.
   Si este define est ausente, est ejecutando su programa en un entorno
   como Windows, el cual no tiene salida estndar.

ALLEGRO_LFN
   Distinto de cero si hay soporte para ficheros de nombres largos, o cero si
   est limitado al formato 8.3 (en la versin DJGPP esto es una variable
   dependiente del entorno durante la ejecucin).

INLINE
   Use esto en lugar de la palabra reservada modificadora de funcin "inline"
   y su cdigo funcionar correctamente en cualquiera de los compiladores
   soportados.

ZERO_SIZE
   Use esto para declarar arrays de tamao cero, ej: "char *line[ZERO_SIZE]"
   dentro de la estructura BITMAP. Algunos compiladores esperan un cero en
   ese lugar, mientras que otros no quieren tener nada dentro de [], por lo
   que esta macro permite que el mismo cdigo funcione bien de cualquier
   modo.

LONG_LONG
   Definido a lo que quiera que represente un entero "long long" de 64 bits
   para el compilador actual, o no definido si no est soportado.

OTHER_PATH_SEPARATOR
   Definido a un carcter separador de ruta distinto de la barra para
   plataformas que lo usen (ej: antibarra bajo DOS y Windows), o definido a
   la barra normal si no hay otro separador de carcter.

DEVICE_SEPARATOR
   Definido al carcter que separa el nombre de fichero del dispositivo (dos
   puntos para DOS y Windows), o cero si no hay dispositivos explcitos en
   las rutas (ej: Unix).

USE_CONSOLE
   Si define esto antes de incluir los ficheros de cabecera de Allegro, la
   versin Windows har que su programa se compile como una aplicacin de
   consola en vez del programa normal en modo grfico.

END_OF_MAIN()
   Al poner esto tras su funcin main() permitir que los programas Windows
   funcionen con una rutina main() regular, para que no tenga que cambiar
   todo para usar WinMain().



==================================================================
============ 39 Reduciendo el tamao de su ejecutable ============
==================================================================

Hay gente que se queja de que Allegro produce ejecutables muy grandes. Esto
es cierto: con la versin DJGPP, un simple programa "hola mundo" ocupar unas
200k, aunque este tamao por ejecutable es mucho menor en plataformas que
soportan enlazado dinmico. Pero no se preocupe, Allegro ocupa un tamao
relativamente fijo, y no aumentar a medida que lo hace su programa. Tal y
como George Foot dijo sin tapujos, quien est preocupado por la relacin
entre cdigo de biblioteca y programa debera ponerse manos a la obra y
escribir ms cdigo de programa para equilibrar la cosa :-)

Dicho esto, hay varias cosas que puede hacer para reducir el tamao de sus
ejecutables:

Para todas las plataformas, puede usar el compresor de ejecutables UPX, el
cual est disponible en http://upx.tsx.org/ . Este normalmente consigue una
compresin de alrededor de un 40%.
Cuando use DJGPP: para empezar, lea la seccin 8.14 del FAQ de DJGPP, y tome
nota del parmetro -s. Y no se olvide de compilar su programa con las
optimizaciones activadas!

Si un programa DOS va a ser usado en un nmero limitado de resoluciones,
puede especificar los controladores grficos que desea incluir con su cdigo:

   BEGIN_GFX_DRIVER_LIST
      driver1
      driver2
      etc...
   END_GFX_DRIVER_LIST

donde los nombres driverx son cualquiera de las definiciones:

   GFX_DRIVER_VBEAF
   GFX_DRIVER_VGA
   GFX_DRIVER_MODEX
   GFX_DRIVER_VESA3
   GFX_DRIVER_VESA2L
   GFX_DRIVER_VESA2B
   GFX_DRIVER_XTENDED
   GFX_DRIVER_VESA1

Esta construccin debe ser incluida slo en uno de sus ficheros C. El orden
de los nombres es importante, porque la rutina de auto deteccin funciona de
arriba a abajo hasta encontrar un controlador capaz de soportar el modo
solicitado. Yo le sugiero que use la lista de arriba ordenada por defecto, y
borre simplemente las lneas que no vaya a necesitar.

Si su programa DOS no necesita usar todas las profundidades de color
posibles, puede especificar cuales desea que sean soportadas por su programa:

   BEGIN_COLOR_DEPTH_LIST
      depth1
      depth2
      etc...
   END_COLOR_DEPTH_LIST

donde los nombres de profundidades de color son cualquiera de los defines:

   COLOR_DEPTH_8
   COLOR_DEPTH_15
   COLOR_DEPTH_16
   COLOR_DEPTH_24
   COLOR_DEPTH_32

Quitar cualquier profundidad de color le ahorrar un poco de espacio, con la
excepcin de los modos de 15 y 16 bits: stos comparten una buena porcin de
cdigo, as que si est incluyendo uno, no hay razn para quitar el otro.
Est avisado de que si intenta usar una profundidad de color no incluida en
esta lista, su programa se colgar de forma horrible!

Del mismo modo que arriba, puede especificar qu controladores de sonido
para DOS quiere incluir en su cdigo:

   BEGIN_DIGI_DRIVER_LIST
      driver1
      driver2
      etc...
   END_DIGI_DRIVER_LIST

usando las definiciones de controladores digitales:

   DIGI_DRIVER_SOUNDSCAPE
   DIGI_DRIVER_AUDIODRIVE
   DIGI_DRIVER_WINSOUNDSYS
   DIGI_DRIVER_SB

y para la msica MIDI:

   BEGIN_MIDI_DRIVER_LIST
      driver1
      driver2
      etc...
   END_MIDI_DRIVER_LIST

usando las definiciones de controladores MIDI:

   MIDI_DRIVER_AWE32
   MIDI_DRIVER_DIGMID
   MIDI_DRIVER_ADLIB
   MIDI_DRIVER_MPU
   MIDI_DRIVER_SB_OUT

Si va a usar alguno de stas construcciones, debe usar las dos. Si slo
quiere incluir controladores de sonido digital, simplemente escriba
DECLARE_MIDI_DRIVER_LIST() para no incluir controladores de msica.

De igual modo para los controladores de joystick de DOS puede declarar una
lista:

   BEGIN_JOYSTICK_DRIVER_LIST
      driver1
      driver2
      etc...
   END_JOYSTICK_DRIVER_LIST

usando las definiciones de controladores de joystick:

   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

El controlador estndar incluye soporte para joysticks duales, nmero
superior de botones, Flightstick Pro, y Wingman Extreme, porque stos son
variaciones menores del cdigo bsico.

Si _realmente_ est decidido a reducir los tamaos, mire el comienzo del
fichero include/allegro/alconfig.h y ver las lneas:

   #define ALLEGRO_COLOR8
   #define ALLEGRO_COLOR16
   #define ALLEGRO_COLOR24
   #define ALLEGRO_COLOR32

Si comenta cualquiera de estas definiciones y reconstruye la librera,
tendr una versin sin soporte para las profundidades de color ausentes, lo
que incluso reducir ms el ejecutable que la macro
DECLARE_COLOR_DEPTH_LIST(). El quitar el define ALLEGRO_COLOR16 eliminar
el soporte para los modos de 15 y 16bits, ya que stos comparten mucho
cdigo.

Nota: los mtodos mencionados para quitar drivers grficos no usados slo es
aplicable a las versiones de la biblioteca enlazadas estticamente, ejemplo:
DOS. En plataformas Windows y Unix, puede crear Allegro como una DLL o
biblioteca compartida, lo cual evita que se puedan usar estos mtodos, pero
ahorra tanto espacio que probablemente ni se llegar a preocupar. No
obstante, quitar profundidades de color de alconfig.h funcionar en cualquier
plataforma.

Si est distribuyendo una copia del programa setup junto con su juego, puede
conseguir una reduccin de tamao dramtica mezclando el cdigo del programa
setup con su programa principal, para que slo sea necesario enlazar una
copia de Allegro. Lea setup.txt para ms detalles. En la versin DJGPP, tras
comprimir su ejecutable, esto le ahorrar unos 200k en comparacin con tener
dos programas separados para setup y el propio juego.



======================================
============ 40 Depurando ============
======================================

Hay tres versiones de la biblioteca Allegro: el cdigo normal optimizado, con
soporte extra para depurar, y una versin para medir el rendimiento. Lea los
ficheros readme especficos de cada plataforma para saber cmo instalar y
enlazar con estas versiones alternativas. A pesar de que obviamente querr
usar la versin optimizada para la versin final de su programa, puede ser
muy til enlazar con la versin de depuracin, porque har la tarea de
depuracin ms fcil, y porque incluye aserciones que le ayudarn a encontrar
errores en su cdigo con antelacin. Allegro contiene varias funciones para
ayudar en la depuracin:

void al_assert(char *file, int line);
   Genera una asercin en el fichero en la lnea especificada. El parmetro
   file debe estar codificado en ASCII. Si ha instalado un controlador propio
   de aserciones lo usa, o si la variable de entorno ALLEGRO_ASSERT escribe
   un mensaje en el fichero especificado por el entorno, y si no, aborta la
   ejecucin del programa con un mensaje de error. Normalmente usar la macro
   ASSERT() en vez de llamar directamente a esta funcin.

void al_trace(char *msg, ...);
   Muestra un mensaje de depuracin usando una cadena con formato printf()
   codificada en ASCII. Si ha instalado una funcin trace propia, ser usada,
   o si la variable de entorno ALLEGRO_TRACE existe se escribir en el
   fichero especificado por sta, en caso contrario se escribir el mensaje
   en "allegro.log" en el directorio actual. Normalmente querr usar la macro
   TRACE() en vez de llamar directamente a esta funcin.

void ASSERT(condition);
   Macro ayudante de depuracin. Normalmente se convierte en nada, pero si ha
   definido DEBUGMODE antes de incluir los ficheros de cabecera de Allegro,
   comprobar la condicin indicada y llamar a al_assert() si sta falla.

void TRACE(char *msg, ...);
register_trace_handler
   Macro ayudante de depuracin. Normalmente se convierte en nada, pero si ha
   definido DEBUGMODE antes de incluir los ficheros de cabecera de Allegro,
   pasar el mensaje (que debe estar codificado en ASCII) a al_trace().

void register_assert_handler(int
(*handler)(char *msg));
register_trace_handler
   Permite usar una funcin propia para tratar las aserciones fallidas. A su
   funcin se le pasar un mensaje de error formateado codificado en ASCII, y
   deber devolver distinto de cero si ha procesado el error, o cero para
   continuar con las acciones por defecto. Puede usar esto para ignorar
   aserciones fallidas, o para mostrar mensajes de error en modo grfico sin
   abortar el programa.

void register_trace_handler(int
(*handler)(char *msg));
register_assert_handler
   Permite usar una funcin propia para tratar los mensajes de trazado. A su
   funcin se le pasar un mensaje de error formateado codificado en ASCII, y
   deber devolver distinto de cero si ha procesado el error, o cero para
   continuar con las acciones por defecto. Puede usar esto para ignorar los
   mensajes de trazado, para mostrarlos en un monitor monocromo secundario,
   etc.



==============================================
============ 41 Comandos makefile ============
==============================================

Hay un nmero de opciones que puede usar para controlar exactamente cmo
compilar Allegro. En plataformas Unix esto se hace pasando argumentos al
script de configuracin (ejecute "configure --help" para obtener una lista),
en otras plataformas puede ajustar las siguientes variables de entorno:

   DEBUGMODE=1
   Genera una versin para depurar, en vez de la versin normal optimizada.

   PROFILEMODE=1
   Genera una versin para medir rendimientos, en vez de la versin normal
   optimizada.

   WARNMODE=1
   Selecciona avisos de compilador ms estrictos. Si est planeando trabajar
   en Allegro, en vez de simplemente usarlo, debera asegurarse de tener este
   modo activado.

   STATICLINK=1 (slo MSVC y Mingw32)
   Enlazar de forma esttica, en vez de usar la DLL por defecto.

   TARGET_ARCH_COMPAT=[cpu] (implementado en la mayora de plataformas GNU)
   Esta opcin optimizar el cdigo para el procesador indicado manteniendo
   a la vez compatibilidad con procesadores anteriores.
   Ejemplo: set TARGET_ARCH_COMPAT=u586

   TARGET_ARCH_EXCL=[cpu] (implementado en la mayora de plataformas GNU)
   Esta opcin optimizar el cdigo para el procesador indicado. Tome nota de
   que el cdigo generado *NO* funcionar en procesadores anteriores.
   Ejemplo: set TARGET_ARCH_EXCL=i586

   TARGET_OPTS=[opts] (implementado en la mayora de plataformas GNU)
   Esta opcin le permite personalizar optimizaciones generales del
   compilador.

   CROSSCOMPILE=1 (slo djgpp)
   Le permite compilar la versin djgpp de la biblioteca bajo Linux, usando
   djgpp como compilador cruzado.

   ALLEGRO_USE_C=1 (slo djgpp)
   Permite generar la biblioteca con djgpp usando el cdigo C de dibujado en
   vez de las rutinas en ensamblador. Esto slo es til para hacer pruebas,
   ya que la versin con ensamblador es ms rpida.

Si usted slo desea recompilar un programa test especfico o una utilidad,
puede especificarlo como parmetro del make, ej: "make demo" o "make
grabber". El makefile tiene adems varios comandos especiales:

   'default'
   El proceso normal. Compila la versin actual de la biblioteca (ya sea
   optimizada, para depurar o medir el rendimiento, seleccionada por las
   variables de entorno anteriores), genera el programa test y los ejemplos,
   y convierte los ficheros de documentacin.

   'all'
   Compila las tres versiones de la biblioteca (optimizada, para depurar
   y para medir rendimiento), genera el programa test y los ejemplos, y
   convierte los ficheros de documentacin.

   'lib'
   Compila la versin actual de la biblioteca (ya sea optimizada, para
   depurar o medir el rendimiento, seleccionada por las variables de entorno
   anteriores).

   'install'
   Copia la versin actual de la biblioteca (ya sea optimizada, para depurar
   o medir el rendimiento, seleccionada por las variables de entorno
   anteriores) en su directorio de bibliotecas, recompilando si es necesario,
   e instala los ficheros de cabecera de Allegro.

   'installall'
   Copia las tres versiones de la biblioteca (ya sea optimizada, para depurar
   o medir el rendimiento, seleccionada por las variables de entorno
   anteriores) en su directorio de bibliotecas, recompilando si es necesario,
   e instala los ficheros de cabecera de Allegro.

   'uninstall'
   Desinstala la biblioteca Allegro y borra los ficheros de cabecera de los
   directorios de su compilador. Esto requiere una utilidad 'rm' de estilo
   Unix, ej: del paquete GNU fileutils.

   'docs'
   Convierte los ficheros de documentacin de las fuentes ._tx.

   'docs-dvi' (slo Unix)
   Crea el fichero de independiente del dispositivo allegro.dvi. Este no es
   un comando por defecto, ya que necesita la herramienta texi2dvi para
   generarlo. El fichero generado est especialmente preparado para ser
   impreso en papel.

  'docs-ps' o 'docs-gzipped-ps' (slo Unix)
   Crea un fichero Postscript a partir del fichero dvi generado previemante.
   Este no es un comando por defecto, ya que necesita las herramientas
   texi2dvi y dvips para generarlo. El segundo comando comprime el fichero
   Postscript generado. El fichero generado est especialmente preparado
   para ser impreso en papel.

   'install-man' o 'install-gzipped-man' (slo Unix)
   Esto genera pginas de manual de Unix para cada funcin o variable de
   Allegro, y las instala. El segundo comando comprime las pginas antes de
   instalarlas.

   'install-info' o 'install-gzipped-info' (slo Unix)
   Convierte la documentacin en formato info y la instala. El segundo
   comando comprime el fichero info antes de instalarlo.

   'clean'
   Elimina todos los ficheros generados del directorio de Allegro, forzando
   una recompilacin total la prxima vez que ejecute make. Este comando est
   diseado de tal forma que si ejecuta "make install" y luego "make clean",
   todava tendr una versin funcional de Allegro . Esto requiere la
   utilidad rm de estilo Unix instalada, por ejemplo del paquete GNU
   fileutils.

   'distclean'
   Como 'make clean', pero ms todava. Elimina todos los archivos
   ejecutables y la documentacin en formato HTML, dejndole con exactamente
   los mismos archivos que hay cuando descomprime una distribucin nueva de
   Allegro.

   'veryclean'
   Use esto con extrema precaucin! Esta orden borra absolutamente todo
   archivo generado, incluyendo algunos que puede ser difcil recrear.
   Despus de ejecutar este comando, una simple recompilacin no funcionar:
   al menos tendr que ejecutar "make depend", y tal vez tambin fixdll.bat
   si est usando la biblioteca de Windows. Este objetivo hace uso de
   herramientas no estndar como SED, as que a no ser que sepa usted lo que
   est haciendo y tenga estas herramientas instaladas, no debera usarlo.

   'depend'
   Regenera los archivos de dependencias (obj/*/makefile.dep). Es necesario 
   ejecutar esto tras "make veryclean", o cuando se le aadan nuevas
   cabeceras a los fuentes de Allegro.

   'compress' (slo djgpp, Mingw32 y MSVC)
   Usa el compresor de ejecutables DJP o UPX (el que tenga instalado) para
   comprimir los programas de ejemplo y las utilidades, lo cual puede
   recuperar una parte significativa de espacio libre en disco.



====================================
============ Conclusin ============
====================================

Todas las cosas buenas tienen un final. Escribir documentacin no es algo
bueno, y eso significa que nunca se acaba la tarea. Siempre hay algo que he
olvidado explicar, o algn detalle esencial que me he dejado, pero por ahora
tendr que sobrevivir con eso. No tenga miedo a preguntar algo si no lo
entiende.

Disfrute. Espero que algo de todo esto le resulte til.


Por Shawn Hargreaves.

http://alleg.sourceforge.net/




