You are on page 1of 549

00 Usando Allegro

• allegro_error
• allegro_exit
• allegro_id
• allegro_init
• allegro_message
• check_cpu
• cpu_capabilities
• cpu_family
• cpu_model
• cpu_vendor
• desktop_color_depth
• get_desktop_resolution
• install_allegro
• os_multitasking
• os_revision
• os_type
• os_version
• set_window_close_button
• set_window_close_hook
• set_window_title
• yield_timeslice

Puede leer en readme.txt una introducción general, detalles de copyright e información


sobre cómo 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 función 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 función. Los identificadores de
sistema disponibles (system_id) variarán dependiendo de la plataforma utilizada, pero casi
siempre querrá usar SYSTEM_AUTODETECT. Alternativamente, SYSTEM_NONE
instalará una versión reducida de Allegro que no intentará realizar accesos directos al
hardware ni operaciones que sean particulares a una plataforma específica: 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 parámetros errno_ptr y atexit_ptr deben apuntar a la variable errno y la
función atexit() de su librería C respectivamente. Estos parámetros son requeridos ya que
cuando Allegro es enlazado como una DLL no tiene acceso directo a los datos locales de su
librería C. atexti_ptr puede ser NULL, en cuyo caso será su responsabilidad llamar
allegro_exit manualmente. Por ahora esta función siempre devuelve cero. Si no se puede
usar ningún driver de sistema, el programa será abortado.
Relacionado con: allegro_init, allegro_exit.

int allegro_init();
Macro que inicia la librería Allegro. Esta función es equivalente a la llamada
install_allegro(SYSTEM_AUTODETECT, &errno, atexit).

Relacionado con: install_allegro, allegro_exit.

void allegro_exit();
Cierra el sistema Allegro. Esto incluye devolver el sistema al modo texto y desinstalar
todas las rutinas de ratón, teclado o temporización que estuviesen instaladas. Normalmente
no tiene que molestarse en hacer una llamada explícita a esta función, ya que allegro_init()
la instala como una función atexit(), por lo que será llamada automáticamente cuando su
programa finalice.

Relacionado con: allegro_init.

extern char allegro_id[];


Cadena de texto que contiene la fecha y número de versión de Allegro, en caso de que
quiera enseñar 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 descripción del problema.

Relacionado con: set_gfx_mode, install_sound.

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

Relacionado con: allegro_init.

extern int os_version;


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

Relacionado con: os_type, os_multitasking.

extern int os_multitasking;


Ajustado por allegro_init() a TRUE o FALSE dependiendo de si su Sistema Operativo es
multitarea o nó.

Relacionado con: os_type, os_version.

void allegro_message(char *msg, ...);


Muestra un mensaje usando una cadena con formato printf(). Esta función sólo debe ser
utilizada cuando no esté en un modo gráfico, es decir, antes de llamar a set_gfx_mode() o
después 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
carácteres acentuados a aproximaciones en 7 bits de códigos ASCII, evitando en lo posible
los problemas con las diferentes páginas de códigos. 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 título de la ventana
utilizada para su programa. Tenga en cuenta que Allegro no es capaz de modificar el título
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 botón de cerrar
ventana de su programa Allegro. Si lo desea, puede llamar esta rutina antes de que la
ventana sea creada. Si el botón de cerrar ventana es desactivado con éxito, esta función
devolverá cero.

En plataformas en las que el botón de cerrado no existe o no puede ser desactivado, la


función devolverá -1. Si esto ocurre, quizás le interese usar set_window_close_hook() para
manejar manualmente el evento de cierre de la ventana.
Cuando active el botón de cierre, la función devolverá el mismo valor que devolvió su
plataforma al desactivarlo. Esto significa que devolverá distinto de cero si el botón no se
puede desacivar, a pesar de que no esté intentando desactivarlo.

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

Relacionado con: set_window_close_hook, set_window_title.

void set_window_close_hook(void (*proc)());


En las plataformas que tengan botón de cierre, esta rutina instala una función de enganche
en el evento de cierre. En otras palabras, cuando el usuario pinche en el botón que cerraría
la ventana de su programa, se llamará a la función que especifique aquí. Puede usar esta
función para mostrar un diálogo ofreciendo salvar los datos o verificar que el usuario
realmente desea salir, o puede usarla para salvar los datos, liberar memoria y salir.

Esta función generalmente no debería intentar salir del programa o salvar datos por sí
misma. Esta función podría ser llamada en cualquier momento, y hay peligro de que los
datos que intente salvar sean inválidos en ese momento. Por eso, debería activar una
variable durante esta función, y verificar esta variable regularmente en su programa
principal.

Pase NULL a esta función para recuperar la funcionalidad por defecto del botón de cierre.
En Windows y BeOS, el siguiente mensaje aparecerá:

Aviso: forzar la finalización del programa puede ocasionar pérdidas 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 traducción 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 botón de cierre de una ventana DOS
bajo Windows.

Relacionado con: set_window_close_button, set_window_title, get_config_text,


three_finger_flag.
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á más si usa la misma profundidad de color. En plataformas
donde esta información no es disponible o no tiene sentido, devuelve cero.

Relacionado con: get_desktop_resolution.

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 resolución actual usada por el escritorio (ej: le itneresará
llamar a esta función 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 número negativo si la información no está disponible o no es aplicable a su
situación, en cuyo caso los valores almacenados en width y heigth serán indefinidos.

Relacionado con: desktop_color_depth.

void yield_timeslice();
En los sistemas que lo soportan, libera el resto de la "rebanada temporal" (timeslice) que la
CPU le había asignado. Esta opción también es conocida como "pórtate 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 función, ya que allegro_init() lo hará por usted.

Relacionado con: cpu_vendor, cpu_family, cpu_model, cpu_capabilities.

extern char cpu_vendor[];


Contiene el nombre del proveedor de la CPU si éste es conocido. En plataformas no-Intel,
contiene una cadena vacía.

Relacionado con: check_cpu, cpu_family, cpu_model, cpu_capabilities.

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.

Relacionado con: check_cpu, cpu_vendor, cpu_model, cpu_capabilities.

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 matemático (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.

Relacionado con: check_cpu, cpu_vendor, cpu_family, cpu_capabilities.

extern int cpu_capabilities;


Contiene bits de la CPU que indican qué características están disponibles. Los bits pueden
ser una combinación de:
CPU_ID - Indica que la instrucción "cpuid" está
disponible.
Si este bit está activo, entonces todas
las variables
CPU de Allegro son fiables al 100%, en
caso contrario
podría 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 - Instrucción "cmov" del Pentium Pro
disponible.

Puede verificar múltiples características haciendo una OR de los bits. Por ejemplo, para ver
si la CPU tiene una FPU y un conjunto de instrucciones MMX podría hacer:

if ((cpu_capabilities & (CPU_FPU | CPU_MMX)) ==


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

Relacionado con: check_cpu, cpu_vendor, cpu_family, cpu_model,


cpu_capabilities.
01 Rutinas Unicode
• _ustrdup
• do_uconvert
• empty_string
• get_uformat
• need_uconvert
• register_uformat
• set_ucodepage
• set_uformat
• uatof
• uconvert
• uconvert_ascii
• uconvert_size
• uconvert_toascii
• ucwidth
• ugetat
• ugetc
• ugetx
• ugetxc
• uinsert
• uisdigit
• uisok
• uisspace
• uoffset
• uremove
• usetat
• usetc
• usprintf
• ustrcat
• ustrchr
• ustrcmp
• ustrcpy
• ustrdup
• ustrerror
• ustricmp
• ustrlen
• ustrlwr
• ustrncat
• ustrncmp
• ustrncpy
• ustrpbrk
• ustrrchr
• ustrsize
• ustrsizez
• ustrstr
• ustrtod
• ustrtok
• ustrtok_r
• ustrtol
• ustrupr
• ustrzcat
• ustrzcpy
• ustrzncat
• ustrzncpy
• uszprintf
• utolower
• utoupper
• uvsprintf
• uvszprintf
• uwidth
• uwidth_max

Allegro puede manipular y mostrar texto usando cualquier carácter en el rango que va de 0
a 2^32-1 (aunque por ahora grabber sólo puede crear fuentes usando carácteres hasta 2^16-
1). Puede escoger entre varios tipos de formatos de codificación de texto, los cuales
controlan la forma en la que las cadenas son almacenadas y cómo Allegro interpreta las que
usted le pase. Esta configuración afecta a todos los aspectos del sistema: cada vez que
observe una función que devuelve un puntero a carácter (char *) o que toma un puntero a
carácter 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 carácteres pueden tener cualquier tamaño de 1 a 6
bytes. Lo bueno de este formato es que los carácteres de 0 a 127 pueden ser almacenados
directamente, o lo que es igual, significa que es compatible con códigos ASCII de 7 bits
("Hola, Mundo!" es exactamente la misma cadena en ASCII que en UTF-8). Cualquier
carácter por encima del 128 como vocales acentuadas, el símbolo monetario inglés o
carácteres árabes y chinos serán codificados como una secuencia de dos o más bytes con un
valor en el rango 128-255. Esto permite que al mostrar la cadena no se obtengan carácteres
extraños en ASCII que en realidad forman parte de la codificación de un carácter con
diferente valor, lo que hace realmente fácil 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 utilización de formatos ASCII
de 8 bits (U_ASCII) o Unicode de 16 bits (U_UNICODE). Además puede programar sus
propias funciones para manejar otros formatos de texto con Allegro (sería sencillo añadir
soporte para el formato UCS-4 de 32 bits, o el formato GB-code chino).

También existe soporte limitado para páginas de códigos alternativas de 8 bits a través del
modo U_ASCII_CP. Lo malo de este modo es que es muy lento y no debería utilizarse para
aplicaciones serias. Sin embargo, puede utilizarse para convertir texto fácilmente entre
diferentes páginas de códigos. 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 páginas de códigos, puede hacerlo pasando
un mapeado de carácteres a la función 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 codificación de texto a utilizar. Esta operación afectará a todos las
funciónes de Allegro que devuelvan un puntero a carácter (char *) o acepten un puntero a
carácter como parámetro. El parámetro type debe ser uno de los siguientes:

U_ASCII - carácteres ASCII de 8 bits de tamaño fijo


U_ASCII_CP - página de códigos alternativa de 8 bits
(ver
set_ucodepage())
U_UNICODE - carácteres Unicode de 16 bits de tamaño
fijo
U_UTF8 - carácteres Unicode UTF-8 de tamaño
variable
Aunque es posible cambiar el formato de texto en cualquier momento, no es una práctica
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 estarán en un formato
diferente al seleccionado y el sistema no funcionará de forma apropiada. Como normal
general, sólo debería llamarse a set_uformat() una vez, antes de llamar a allegro_init(), y
utilizar el formato de texto seleccionado durante toda la ejecución de su programa.

Relacionado con: get_uformat, register_uformat, set_ucodepage, set_uformat,


uconvert, ugetat, usetat, uinsert, uremove, allegro_init, ustrsize, ugetc, ugetx,
usetc, uwidth, ucwidth, uisok, uoffset.

int get_uformat(void);
Devuelve el formato de codificación de texto actualmente seleccionado.

Relacionado con: set_uformat.

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 codificación de
carácteres. El parámetro type identifica el nuevo formato, que debería ser una cadena de 4
carácteres 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 parámetros, son manejadores que implementan el acceso a los carácteres de
una cadena formateada con la nueva codificación (vea más abajo para más detalles).

Relacionado con: set_uformat, uconvert, ugetc, ugetx, usetc, uwidth, ucwidth,


uisok.

void set_ucodepage(const unsigned short *table, const unsigned short *extras);


Cuando se selecciona el modo U_ASCII_CP, los carácteres de 8 bits son convertidos a sus
equivalentes en Unicode a través de un conjunto de tablas. Se puede usar esta función para
especificar un conjunto de tablas personalizadas que permitan la utilización de páginas de
códigos de 8 bits alternativas. El parámetro table apunta a un array de 256 enteros short que
contienen el valor Unicode para cada carácter en la página de códigos. El parámetro extras,
si no es NULL, apunta a una lista de pares de valores que es utilizada para realizar la
conversión inversa, es decir, reducir los valores Unicode a la representación correcta dentro
de la nueva página de codigos. Cada par de valores consiste en un valor Unicode seguido
por la forma de representación correspondiente dentro de la página de códigos. La tabla
debe finalizar con el valor cero en Unicode. Esta tabla permite que varios carácteres
Unicode puedan representarse mediante un solo valor en la página de codigos (por ejemplo
para reducir vocales acentuadas a ASCII de 7 bits).

Relacionado con: set_uformat.

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
función indica si dicha conversión es necesaria. La conversión 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 carácteres menores que 128). Como valor para uno de los parámetros type,
se puede pasar U_CURRENT que representa el tipo actualmente seleccionado.

Relacionado con: set_uformat, get_uformat, do_uconvert, uconvert.

int uconvert_size(const char *s, int type, int newtype);


Devuelve el número de bytes que serán necesarios para almacenar la cadena especificada
tras una conversión al nuevo tipo, incluyendo el carácter terminador nulo. Los parámetros
type pueden usar el valor U_CURRENT para indicar el tipo actualmente seleccionado.

Relacionado con: need_uconvert, do_uconvert.

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 parámetros type pueden utilizar el valor U_CURRENT para
indicar el tipo actualmente seleccionado.
Relacionado con: uconvert.

char *uconvert(const char *s, int type, char *buf, int newtype, int size);
Esta es una función 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 conversión, para asegurarse de
que son tipos diferentes, no realizando conversión alguna si los tipos son iguales o
equivalentes. Si la conversión 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 estático interno. Sin embargo, debería 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.

Relacionado con: set_uformat, need_uconvert, uconvert, uconvert_ascii,


uconvert_toascii.

char *uconvert_ascii(const char *s, char buf[]);


Macro auxiliar para convertir cadenas desde ASCII al formato actual de codificación. Se
expande a uconvert(s, U_ASCII, buf, U_CURRENT, sizeof(buf)).

Relacionado con: uconvert.

char *uconvert_toascii(const char *s, char buf[]);


Macro auxiliar para convertir cadenas desde el formato actual de codificación a ASCII. Se
expande a uconvert(s, U_CURRENT, buf, U_ASCII, sizeof(buf)).

Relacionado con: uconvert.

extern char empty_string[];


No se puede fiar de que "" sea una cadena vacía válida en todos los formatos de
codificación. Este búffer global contiene un número de ceros consecutivos, así que siempre
será una cadena vacía válida, sin tener importancia si el programa se está ejecutando en
modo ASCII, Unicode o UTF-8.

int ugetc(const char *s);


Función auxiliar de bajo nivel para leer datos de texto en Unicode. Dado un puntero a una
cadena en el formato de codificación actual devuelve el siguiente caracter de la cadena.

Relacionado con: ugetx, usetc, uwidth, ucwidth, uisok.


int ugetx(char **s);
int ugetxc(const char **s);
Función auxiliar de bajo nivel para leer datos de texto en Unicode. Dada la dirección de un
puntero a un string en el formato de codificación 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.

Relacionado con: ugetc, usetc, uwidth, ucwidth, uisok.

int usetc(char *s, int c);


Función auxiliar de bajo nivel para escribir datos de texto en Unicode. Escribe el caracter
especificado en la dirección dada usando el formato de codificación actual y devuelve el
número de bytes escritos.

Relacionado con: ugetc, ugetx, uwidth, ucwidth, uisok.

int uwidth(const char *s);


Función auxiliar de bajo nivel para comprobar datos de texto en Unicode. Devuelve el
número de bytes ocupados por el primer caracter de la cadena especificada en el formato de
codificación actual.

Relacionado con: uwidth_max, ugetc, ugetx, usetc, ucwidth, uisok.

int ucwidth(int c);


Función auxiliar de bajo nivel para comprobar datos de texto en Unicode. Devuelve el
número de bytes que ocuparía el caracter especificado en caso de codificarse en el formato
actual.

Relacionado con: uwidth_max, ugetc, ugetx, usetc, uwidth, uisok.

int uisok(int c);


Función 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.

Relacionado con: ugetc, ugetx, usetc, uwidth, ucwidth.

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 hacía atrás desde el
final de la cadena, así que un índice de -1 devolverá un desplazamiento al último caracter.

Relacionado con: ugetat, usetat, uinsert, uremove.


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

Relacionado con: uoffset, usetat, uinsert, uremove.

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 había antes en esa posición). Devuelve el número de bytes que ha
sido desplazada la parte derecha de la cadena. Si el índice es negativo cuenta hacia atrás
desde el final de la cadena.

Relacionado con: uoffset, ugetat, uinsert, uremove.

int uinsert(char *s, int index, int c);


Inserta el caracter c en la posición de la cadena especificada por index, desplazando el resto
de los datos para hacer sitio. Devuelve el número de bytes que ha desplazado la parte
derecha. Si el índice es negativo cuenta hacia atras desde el final de la cadena.

Relacionado con: uoffset, ugetat, usetat, uremove.

int uremove(char *s, int index);


Borra el caracter que hay en la posición index de la cadena, desplazando el resto de los
datos para llenar la posición vacía. Devuelve el número 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

Relacionado con: uoffset, ugetat, usetat, uinsert.

int ustrsize(const char *s);


Devuelve el tamaño de la cadena especificada en bytes, sin incluir el caracter nulo
finalizador de cadena.

Relacionado con: ustrsizez.

int ustrsizez(const char *s);


Devuelve el tamaño de la cadena especificada en bytes, incluyendo el caracter nulo
finalizador de cadena.

Relacionado con: ustrsize.


int uwidth_max(int type);
Rutinas ayudantes de bajo nivel para trabajar con texto Unicode. Devuelven el mayor
número de bytes que un carácter puede ocupar en el formato de codificación especificado.
Pase U_CURRENT para indicar el formato de codificación actual.

Relacionado con: uwidth, ucwidth.

int utolower(int c);


Esta función devuelve c, convirtiéndola a minúsculas si estaba en mayúsculas.

Relacionado con: utoupper, ugetc, ugetx, usetc, uwidth, ucwidth, uisok.

int utoupper(int c);


Esta función devuelve c, convirtiéndola a mayúsculas si estaba en minúsculas.

Relacionado con: utolower, ugetc, ugetx, usetc, uwidth, ucwidth, uisok.

int uisspace(int c);


Devuelve distinto de cero si c es carácter de espaciado, es decir, un retorno de carro, una
nueva línea, página, un tabulador, un tabulador vertical o un espacio.

Relacionado con: uisdigit, ugetc, usetc, uwidth, ucwidth, uisok.

int uisdigit(int c);


Devuelve distinto de cero si c es un dígito.

Relacionado con: uisspace, ugetc, usetc, uwidth, ucwidth, uisok.

char *ustrdup(const char *src)


Esta función 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.

Relacionado con: _ustrdup, uconvert, ustrsize, ustrsizez.

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.

Relacionado con: ustrdup, uconvert, ustrsize, ustrsizez.

char *ustrcpy(char *dest, const char *src);


Esta función copia src en dest (incluyendo el terminador de cadena NULL). El valor de
retorno es el valor de dest.
Relacionado con: uconvert, ustrsize, ustrsizez, ustrncpy.

char *ustrzcpy(char *dest, int size, const char *src);


Esta función 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 carácter NULL. El
valor de retoron es el valor de dest.

Relacionado con: uconvert, ustrcpy, ustrzncpy.

char *ustrcat(char *dest, const char *src);


Esta función concatena src al final de dest. El valor de retorno es el valor de dest.

Relacionado con: uconvert, ustrzcat, ustrncat.

char *ustrzcat(char *dest, int size, const char *src);


Esta función concatena src al final de dest, cuya longitud en bytes es especificada por size y
que está garantizado que termine en carácter NULL. El valor de retorno es el valor de dest.

Relacionado con: uconvert, ustrcat, ustrzncat.

int ustrlen(const char *s);


Esta función devuelve el número de carácteres de s. Tenga en cuenta que esto no tiene que
ser igual que el tamaño de la cadena en bytes.

Relacionado con: uconvert, ustrsize, ustrsizez.

int ustrcmp(const char *s1, const char *s2);


Esta función compara s1 con s2. Devuelve cero si las cadenas son iguales, un número
positivo si s1 va detrás de s2 en la secuencia ASCII apropiada, o negativo en caso contrario.

Relacionado con: uconvert, ustrsize, ustrsizez, ustrncmp, ustricmp.

char *ustrncpy(char *dest, const char *src, int n);


Esta función es como ustrcpy() excepto que no copiará más de n carácteres de src a dest. Si
src es menor en longitud que n carácteres, se añadirán carácteres NULL en dest hasta
rellenar los n carácteres especificados. Note que si src es mayor que n carácteres, dest no
terminará en NULL. El valor de retorno es el valor de dest.

Relacionado con: uconvert, ustrcpy, ustrzncpy.

char *ustrzncpy(char *dest, int size, const char *src, int n);
Esta función es como ustrzcpy() excepto que no copiará más de n carácteres de src a dest.
Si src es menor en longitud que n carácteres, se añadirán carácteres NULL en dest hasta
rellenar los n carácteres especificados. Note que está garantizado que dest acabe en carácter
NULL. El valor de retorno es el valor de dest.

Relacionado con: uconvert, ustrzcpy, ustrncpy.

char *ustrncat(char *dest, const char *src, int n);


Esta función es como `strcat' con la excepción de que no se añadirán más de n bytes de src
al final de dest. Si el carácter terminador NULL es encontrado en src antes de haber escrito
n carácteres, el carácter NULL será copiado, pero no se escribirán más carácteres. Si n
carácteres son copiados antes de encontrar el carácter NULL, la función añadirá
automáticamente el carácter NULL a dest, por lo que se escribirán n+1 carácteres. El valor
de retorno es dest.

Relacionado con: uconvert, ustrcat, ustrzncat.

char *ustrzncat(char *dest, int size, const char *src, int n);
Esta función es como ustrszcat() con la excepción de que no se añadirán más de n
carácteres de src al final de dest. Si el carácter terminador NULL es encontrado en src antes
de haber escrito n carácteres, el carácter NULL será copiado, pero no se escribirán más
carácteres. Note que está garantizado que dest acabe en carácter NULL. El valor de retorno
es el valor de dest.

Relacionado con: uconvert, ustrzcat, ustrncat.

int ustrncmp(const char *s1, const char *s2, int n);


Esta función compara hasta n carácteres de s1 con s2. Devuelve cero si las cadenas son
iguales, un número positivo si s1 va detrás de s2 en la secuencia ASCII apropiada, o
negativo en caso contrario.

Relacionado con: uconvert, ustrsize, ustrsizez, ustrcmp, ustricmp.

int ustricmp(const char *s1, const char *s2);


Esta función compara s1 con s2, ignorando las mayúsculas.

Relacionado con: uconvert, ustrsize, ustrsizez, ustrcmp, ustrncmp.

char *ustrlwr(char *s);


Esta función sustituye todas las letras mayúsculas de s con minúsculas.

Relacionado con: uconvert, utolower, ustrupr.

char *ustrupr(char *s);


Esta función sustituye todas las letras minúsculas de s con mayúscylas.
Relacionado con: uconvert, utolower, ustrlwr.

char *ustrchr(const char *s, int c);


Esta función 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 función devolverá un puntero al final de
la cadena.

Relacionado con: uconvert, ustrrchr, ustrstr, ustrpbrk, ustrtok.

char *ustrrchr(const char *s, int c);


Esta función devuelve un puntero a la última ocurrencia de c en s, o NULL si s no contiene
c.

Relacionado con: uconvert, ustrchr, ustrstr, ustrpbrk, ustrtok.

char *ustrstr(const char *s1, const char *s2);


Esta función busca la primera ocurrencia de s2 en s1. Devuelve un puntero dentro de s1, o
NULL si s2 no fue encontrada.

Relacionado con: uconvert, ustrchr, ustrrchr, ustrpbrk, ustrtok.

char *ustrpbrk(const char *s, const char *set);


Esta función encuentra el primer carácter de s que esté contenido en set. Devuelve un
puntero a la primera ocurrencia, o NULL si no se encontró nada.

Relacionado con: uconvert, ustrchr, ustrrchr, ustrstr, ustrtok.

char *ustrtok(char *s, const char *set);


Esta función recupera palabras de s que están delimitadas por carácteres de set. Para iniciar
la búsqueda, 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. Además, esta función no es reentrante (ej:
no puede analizar dos cadenas simultáneamente).

Relacionado con: uconvert, ustrchr, ustrrchr, ustrstr, ustrpbrk, ustrtok_r.

char *ustrtok_r(char *s, const char *set, char **last);


Versión reentrante de ustrtok. El último parámetro es usado para almacenar por dónde 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.

Relacionado con: ustrtok.


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

Relacionado con: uconvert, ustrtol, ustrtod.

long ustrtol(const char *s, char **endp, int base);


Esta función 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 carácter no convertido, si
endp no es un puntero nulo. Si el parámetro 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.

Relacionado con: uconvert, ustrtod, uatof.

double ustrtod(const char *s, char **endp);


Convierte en número de coma flotante tantos carácteres de s que parezcan un número en
coma flotante, y hace que *endp apunte al primer carácter no usado, si endp no es un
puntero nulo.

Relacionado con: uconvert, ustrtol, uatof.

const char *ustrerror(int err);


Esta función devuelve una cadena que describe el código de error `err', que normalmente
vendrá de la variable `errno'. Devuelve un puntero a una cadena estática que no debe ser
modificada o liberada. Si hace llamadas posteriores a ustrerror, la cadena puede ser
sobreescrita.

Relacionado con: uconvert, allegro_error.

int usprintf(char *buf, const char *format, ...);


Esta función escribe datos formateados en el buffer de salida. El carácter NULL es escrito
para marcar el final de la cadena. Devuelve el número de carácteres que fueron escritos, sin
incluír el carácter terminador nulo.

Relacionado con: uconvert, uszprintf, uvsprintf.

int uszprintf(char *buf, int size, const char *format, ...);


Esta función escribe datos formateados en el buffer de salida, cuya longitud en bytes es
especificada por size, y que está garantizado que acabará en carácter NULL. Devuelve el
número de carácteres que se hubiesen escrito sin contar la truncación eventual (como con
usprintf), y sin incluír el carácter 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.

Relacionado con: uconvert, usprintf, uvszprintf.

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.

Relacionado con: uconvert, uszprintf, uvsprintf.

03 Rutinas de ratón
• freeze_mouse_flag
• get_mouse_mickeys
• install_mouse
• mouse_b
• mouse_callback
• mouse_needs_poll
• mouse_pos
• mouse_sprite
• mouse_x
• mouse_x_focus
• mouse_y
• mouse_y_focus
• poll_mouse
• position_mouse
• position_mouse_z
• remove_mouse
• scare_mouse
• scare_mouse_area
• set_mouse_range
• set_mouse_speed
• set_mouse_sprite
• set_mouse_sprite_focus
• show_mouse
• unscare_mouse

int install_mouse();
Instala el controlador del ratón de Allegro. Debe hacer esto antes de usar cualquier otra
función del ratón. Devuelve -1 si hubo error (ej. si el controlador int33 no está cargado), o
el número de botones del ratón.
Relacionado con: position_mouse, set_mouse_range, set_mouse_speed,
remove_mouse, poll_mouse, mouse_x, show_mouse, get_mouse_mickeys,
Variables de configuración estándar.

void remove_mouse();
Quita el controlador de ratón. Normalmente no necesita llamar esta función, porque
allegro_exit() lo hará por usted.

Relacionado con: install_mouse, allegro_exit.

int poll_mouse();
Siempre que sea posible, Allegro leerá la entrada del ratón asíncronamente (ej: dentro de
una interrupción), 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 ratón.
Para ayudarle a comprobar que su código de muestreo del ratón 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
función para obtener cualquier dato del ratón, sin importar si el controlador actual necesita
ser muestreado o nó. Devuelve cero con éxito, o un número negativo si hubo un fallo (ej:
no hay driver de ratón instalado).

Relacionado con: mouse_needs_poll, install_mouse, mouse_x.

int mouse_needs_poll();
Devuelve TRUE si el controlador de ratón actual está siendo operado en modo muestreo.

Relacionado con: poll_mouse, install_mouse, mouse_x.

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 posición actual del ratón 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 botón: bit
0 es el botón izquierdo, bit 1 es del derecho, y bit 2 el botón central. Por ejemplo:
if (mouse_b & 1)
printf("El botón izquierdo está pulsado\n");

if (!(mouse_b & 2))


printf("El botón 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 rápidos de lectura donde una interrupción del ratón
podría ocurrir mientras lee las dos variables por separado, ya que puede copiar este valor a
una variable local con una instrucción, y entonces separarlo con tranquilidad.
Relacionado con: install_mouse.

extern BITMAP *mouse_sprite;


extern int mouse_x_focus;
exterm int mouse_y_focus;
Variables globales que contienen el sprite actual del ratón y el punto del foco. Estas
variables sólo son de lectura, y sólo se pueden modificar usando las funciones
set_mouse_sprite() y set_mouse_sprite_focus().

Relacionado con: set_mouse_sprite, set_mouse_sprite_focus.

void show_mouse(BITMAP *bmp);


Le dice a Allegro que muestre el puntero del ratón en la pantalla. Esto sólo funcionará si el
módulo de temporización está instalado. El puntero del ratón será dibujado sobre el bitmap
especificado, que será normalmente 'screen' (lee más abajo información sobre bitmaps).
Para ocultar el puntero del ratón, llame show_mouse(NULL). Aviso: si dibuja algo en la
pantalla mientras el puntero está visible, podría ocurrir una interrupción de movimiento en
medio de su operación de dibujo. Si esto ocurre, el buffer del ratón y el código de cambio
de banco SVGA se confundirán, y dejarán 'rastros de ratón' por toda la pantalla. Para evitar
esto, debe asegurarse que oculta el puntero del ratón siempre que vaya a dibujar la pantalla.

Relacionado con: freeze_mouse_flag, install_mouse, install_timer,


set_mouse_sprite, scare_mouse.

void scare_mouse();
Función de ayuda para ocultar el puntero del ratón antes de una operación de dibujado. Esto
se deshará temporalmente del puntero del ratón, pero sólo si es realmente necesario (ej. el
ratón es visible, y está siendo visualizado en la pantalla física, y no se trata de un cursor por
hardware). El estado previo del ratón es almacenado para las llamadas siguientes a
unscare_mouse().

Relacionado con: unscare_mouse, show_mouse.

void scare_mouse_area(int x, int y, int w, int h);


Como scare_mouse(), pero sólo ocultará el cursor si éste se encuentra dentro del rectángulo
especificado. Si no lo está, el cursor simplemente será congelado hasta que llame a
unscare_mouse(), para que no pueda interferir con su dibujado.

Relacionado con: unscare_mouse, scare_mouse_area, show_mouse.

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

Relacionado con: scare_mouse.


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

Relacionado con: show_mouse.

void position_mouse(int x, int y);


Mueve el ratón a la posición de pantalla especificada. Puede llamar esta función incluso
mientras el puntero esté visible.

Relacionado con: install_mouse, set_mouse_range, set_mouse_speed.

void position_mouse_z(int z);


Establece la variable que contiene la posición de la ruedecilla del ratón al valor indicado.

Relacionado con: install_mouse, position_mouse.

void set_mouse_range(int x1, int y1, int x2, int y2);


Crea un área de pantalla sobre la que el ratón se podrá desplazar. Pase los parámetros de las
esquinas del recuadro (coordenadas inclusivas). Si no llama esta función, el área por
defecto se activará a (0, 0, SCREEN_W-1, SCREEN_H-1).

Relacionado con: install_mouse, set_mouse_speed, position_mouse.

void set_mouse_speed(int xspeed, int yspeed);


Ajusta la velocidad del ratón. Valores grandes de xspeed e yspeed significan un
movimiento más lento: por defecto ambos son 2.

Relacionado con: install_mouse, set_mouse_range, position_mouse.

void set_mouse_sprite(BITMAP *sprite);


¿No le gusta mi puntero de ratón? No problemo. Use esta función 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 bonificación, 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).

Relacionado con: install_mouse, show_mouse, set_mouse_sprite_focus.

void set_mouse_sprite_focus(int x, int y);


El foco del ratón es la parte del puntero que representa la posición actual del ratón, vamos,
la posición (mouse_x, mouse_y). Por defecto el foco está arriba a la izquierda de la flecha,
pero si va a usar un puntero de ratón diferente, quizás deba alterar esto.

Relacionado con: set_mouse_sprite.

void get_mouse_mickeys(int *mickeyx, int *mickeyy);


Mide cómo de lejos se ha movido el ratón desde la última llamada a esta función. El ratón
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 ratón infinito.

Relacionado con: install_mouse.

extern void (*mouse_callback)(int flags);


Llamado por el controlador de interrupciones siempre cuando el ratón se mueva o el valor
de los botones cambie. Esta función debe ser bloqueada en memoria (locked), y debe
ejecutarse ¡muy rápido! Se le pasan los bits de evento que activaron la llamada, que son una
máscara 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.

Relacionado con: install_mouse.

04 Rutinas de temporización
• install_int
• install_int_ex
• install_param_int
• install_param_int_ex
• install_timer
• remove_int
• remove_param_int
• remove_timer
• rest
• rest_callback
• retrace_count
• retrace_proc
• timer_can_simulate_retrace
• timer_is_using_retrace
• timer_simulate_retrace

Allegro puede establecer varias funciones virtuales de temporización, todas funcionando a


diferentes velocidades.
Bajo DOS reprogramará el reloj contínuamente para asegurarse de que todas se llaman en
el momento adecuado. Dado que estas rutinas alteran el chip de temporización de bajo
nivel, estas rutinas no deben usarse con otras rutinas de temporización del DOS, como la
rutina uclock() del djgpp.

En otras plataformas están implementados usando hilos, que corren de forma paralela al
hilo principal. Por lo tanto las rutinas de llamada instaladas con temporizadores no
bloquearán al hilo principal cuando sean llamadas, por lo que podría necesitar dispositivos
de sincronización apropiados (ej: semáforos, mutexes, etc) cuando acceda a datos
compartidos por el hilo principal y su rutina de temporización. (Por ahora Allegro no
provee este tipo de dispositivos de sincronización.)

int install_timer();
Instala el controlador de temporización de Allegro. Debe hacer esto antes de instalar
cualquier rutina de temporización propia, e incluso antes de visualizar el puntero del ratón,
reproducir una animación FLI, reproducir música MIDI y usar cualquiera de las rutinas
GUI. Devuelve cero con éxito, o un número negativo si hubo problemas (pero puede
decidir si quiere verificar el valor de retorno de esta función, dado que es muy poco
probable que pueda fallar).

Relacionado con: remove_timer, install_int.

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

Relacionado con: install_timer, allegro_exit.

int install_int(void (*proc)(), int speed);


Instala un temporizador con el tiempo dado en número 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 módulo de temporización, install_timer() será llamado
automáticamente. Si no hay más espacio para añadir otro temporizador de usuario,
install_int() devolverá un número negativo, en otro caso devolverá cero.

Relacionado con: install_timer, remove_int, install_int_ex.

int install_int_ex(void (*proc)(), int speed);


Añade una función 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 número de segundos entre
cada tick
MSEC_TO_TIMER(msec) - pase el número de milisegundos
entre cada tick
BPS_TO_TIMER(bps) - pase el número de ticks por
segundo
BPM_TO_TIMER(bpm) - pase el número de ticks por
minuto
Si no queda espacio para un temporizador nuevo, install_int_ex() devolverá un número
negativo, o cero de otro modo. Sólo puede haber 16 temporizadores a la vez, y algunas
partes de Allegro (código GUI, rutinas para visualizar el puntero del ratón, rest(), el
reproductor de ficheros FLI o MIDI) necesitan instalar sus propios temporizadores, por lo
que debería evitar usar muchos a la vez.

Su función será llamada por el controlador de interrupciones de Allegro y no directamente


por el procesador, por lo que puede ser una función normal en C, y no necesita ninguna
función de envoltura. Sin embargo tenga en cuenta que será llamada en contexto de
interrupción, lo que impone muchas restricciones sobre lo que puede hacer en ella. No
debería usar grandes cantidades de pila, no puede hacer llamadas al sistema operativo o
usar funciones de la biblioteca de C, o contener código con operaciones en coma flotante, y
debe ejecutarse rápidamente. No intente hacer cosas complicadas con su temporizador:
como regla general debería 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 paginación al disco ocurre
dentro de su función de temporización, el sistema morirá de forma dolorosa, por lo que
debe asegurarse de bloquear (lock) toda la memoria (de código y datos) que sea modificada
dentro de su rutina de temporización. Allegro bloqueará todo lo que use, pero usted es
responsable de bloquear su rutina de temporización. 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, debería
escribir:

volatile int contador;

void mi_temporizador()
{
contador++;
}

END_OF_FUNCTION(mi_temporizador);
y en su código de inicio debería bloquear la memoria de esta manera:
LOCK_VARIABLE(contador);
LOCK_FUNCTION(mi_temporizador);
Obviamente esto puede ser extraño si usa estructuras de datos complicadas y llama otras
funciones desde su temporizador, por lo que debería crear sus temporizadores tan simples
como pueda.
Relacionado con: install_timer, remove_int, install_int.

void remove_int(void (*proc)());


Quita una función de la lista de temporizadores de usuario. Al finalizar su programa,
allegro_exit() hará esto automáticamente.

Relacionado con: install_int, install_int_ex.

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

Relacionado con: install_timer, remove_param_int, install_param_int_ex,


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

Relacionado con: install_timer, remove_param_int, install_param_int,


install_int_ex.

void remove_param_int(void (*proc)(void *), void *param);


Como remove_int(), pero se usa con las rutinas de temporización que tienen parámetros. Si
hay más de una copia de la misma rutina activa a la vez, elegirá la rutina a desactivar
comprobando el valor del parámetro (por lo que no puede tener más de una copia de un
mismo temporizador usando un parámetro idéntico).

Relacionado con: install_param_int, install_param_int_ex, remove_int.

int timer_can_simulate_retrace()
Comprueba si es posible sincronizar el módulo de temporización con el retrazo del monitor,
dependiendo del entorno y plataforma actual (por el momento esto sólo es posible
ejecutándo un el programa en modo DOS puro y en una resolución VGA o modo-X).
Devuelve distinto de cero si la simulación es posible.

Relacionado con: timer_simulate_retrace, timer_is_using_retrace.

void timer_simulate_retrace(int enable);


El controlador DOS de temporización puede ser usado para simular interrupciones de
retrazo vertical. Una interrupción de retrazo puede ser extremadamente útil para
implementar una animacion suave, pero desafortunadamente el hardware de la VGA no
puede hacerlo. La Ega lo podía 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 unterrupción cuando crea que va a ocurrir, y
leyendo la VGA dentro del controlador de interrupción 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 mayoría de las implementaciones VESA. La
simulación de retrazo sólo es fiable en el modo 13 de la VGA y en el modo-X.

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

- La simulación de retrazo conlleva mucha espera del controlador de temporización con las
interrupciones desactivadas. Esto reducirá la velocidad del sistema de forma significante, y
podría causar estática el reproducir sonidos con tarjetas SB 1.0 (ya que no soportan la auto-
inicialización DMA: las SB 2.0 y superiores funcionarán bien).

Considerando todos estos problemas, se aconsejaría 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 sería buena idea dejar al usuario la posibilidad de desactivarlo.

La simulación de retrazo debe ser activada antes de usar las funciones de triple buffer en
resoluciones del modo-X. Esto puede ser útil también como una simple detección de
retrazo, ya que leer vsync() puede hacer que ignore algún retrazo de vez en cuando si justo
una interrupción de sonido o temporización ocurre a la vez. Cuando la simulación de
retrazo está activada, vsync() comprobará la variable retrace_count en vez de leer los
registros de la VGA, para que no pierda ningún retrazo incluso si está siendo enmascarado
por otras interrupciones.

Relacionado con: enable_triple_buffer, install_timer, retrace_count, retrace_proc,


request_scroll, vsync, timer_can_simulate_retrace, timer_is_using_retrace.

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

Relacionado con: timer_simulate_retrace, timer_can_simulate_retrace.

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 temporización
propias.
La velocidad del retrazo depende del modo gráfico. En el modo 13h y resoluciones en
modo-X de 200/400 líneas hay 70 retrazos por segundo, y en modos-X de 240/480 líneas
hay 60. Puede ser tan bajo como 50 (en modo 376x282) o tan alto como 92 (en modo
400x300).

Relacionado con: timer_simulate_retrace, retrace_proc.

extern void (*retrace_proc)();


Si el simulador de retrazo está instalado, esta función será llamada durante cada retrazo, de
otro modo es llamada 70 veces por segundo (ignorando los retrazos). Póngala a NULL para
desactivar las llamadas. Esta función 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 más: debe ejecutarse _muy_ rápido, o fastidiará la sincronización del
reloj. El único uso que veo para esta función es para hacer manipulaciones de paleta, ya que
el triple buffering puede hacerse con la función request_scroll(), y la variable retrace_count
puede ser usada para temporizar su código. Si quiere alterar la paleta dentro de
retrace_proc, debe usar la función inline _set_color() en vez de la corriente set_color() o
set_palette(), y no debería intentar alterar más de dos o tres colores de la paleta en un
mismo retrazo.

Relacionado con: _set_color, timer_simulate_retrace, timer_is_using_retrace,


retrace_count.

void rest(long time);


Una vez que Allegro reprograma el reloj, la función estándar delay() no funcionará, por lo
que tendrá que usar ésta. El tiempo time se pasa en milisegundos.

Relacionado con: install_timer, rest_callback.

void rest_callback(long time, void (*callback)())


Como rest(), pero llama continuamente la función específica mientras está esperando que
pase el tiempo requerido.

Relacionado con: install_timer, rest.

05 Rutinas de teclado
• clear_keybuf
• install_keyboard
• install_keyboard_hooks
• key
• key_led_flag
• key_shifts
• keyboard_callback
• keyboard_lowlevel_callback
• keyboard_needs_poll
• keyboard_ucallback
• keypressed
• poll_keyboard
• readkey
• remove_keyboard
• scancode_to_ascii
• set_keyboard_rate
• set_leds
• simulate_keypress
• simulate_ukeypress
• three_finger_flag
• ureadkey

El controlador de teclado de Allegro proporciona entrada con búffer y un conjunto de


variables que guardan el estado actual de cada tecla. Fíjese que no es posible detectar
correctamente todas y cada una de las combinaciones de teclas, debido al diseño del teclado
del PC. Combinaciones de dos o tres teclas funcionarán bien, pero si presiona más,
probablemente las extras serán 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 función de teclado. Una vez instalado el controlador no podrá usar las
llamadas a sistema o las funciones de librería de C para acceder al teclado. Devuelve cero
con éxito, o un número negativo si hubo problemas (pero puede decidir si quiere verificar el
valor de retorno dado que es muy poco probable que esta función falle). Tenga en cuenta
que en algunas plataformas el teclado no funcionará a no ser que haya activado un modo
gráfico, incluso si esta función devuelve cero antes de haber llamado a set_gfx_mode.

Relacionado con: keyboard_callback, keyboard_ucallback,


keyboard_lowlevel_callback, remove_keyboard, poll_keyboard, key, keypressed,
readkey, ureadkey, set_gfx_mode, Variables de configuración estándar,
three_finger_flag, key_led_flag, set_leds, set_keyboard_rate.

void remove_keyboard();
Desintala el controlador de teclado, devolviendo el control al sistema operativo.
Normalmente no necesita llamar a esta función, porque allegro_exit() lo hará por usted.

Relacionado con: install_keyboard, allegro_exit.

void install_keyboard_hooks(int (*keypressed)(), int (*readkey)());


Sólo debería 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 atención para
detectar y leer pulsaciones de teclado, que serán usadas por las funciones principales
keypressed() y readkey(). Esto puede ser útil si quiere usar el código GUI de Allegro con
un controlador de teclado propio, ya que permite al GUI acceder a la entrada de teclado
desde su código, saltándose el sistema de entrada normal de Allegro.

Relacionado con: install_keyboard, keypressed, readkey.

int poll_keyboard();
Siempre que sea posible Allegro intentará leer del teclado asíncronamente (por ejemplo
deste un controlador de interrupción), 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 código que muestrea el
teclado incluso si está programando en una plataforma que no lo necesita, después 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
leído o no. La funciones keypressed(), readkey() y ureadkey() llaman a poll_keyboard()
automáticamente, así que sólo tendra que usar esta función cuando acceda al array key[] y a
la variable key_shifts. Devuelve cero con éxito, o un número negativo si hubo algún
problema (ej: no hay driver de teclado instalado).

Relacionado con: keyboard_needs_poll, install_keyboard, key, key_shifts.

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

Relacionado con: poll_keyboard, install_keyboard, key.

extern volatile char key[KEY_MAX];


Array de enteros que indica el estado de cada tecla, ordenado por scancode. Siempre que
sea posible se actualizarán estos valores de forma asíncrona, pero si keyboard_needs_poll()
devuelve TRUE, deberá llamar manualmente a poll_keyboard() para actualizarlos con el
estado actual. Los scancodes están definidos en allegro/keyboard.h como una serie de
constantes KEY_* (abajo tiene un listado). Por ejemplo, podría 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 están físicamente
apretadas y cuales nó, por lo que semánticamente sólo 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

Relacionado con: install_keyboard, poll_keyboard, key_shifts.

extern volatile int key_shifts;


Máscara de bits que contienen el estado actual de shift/ctrl/alt, de las teclas especiales de
Windows y los carácteres de escape de los acentos. Siempre que sea posible se actualizarán
estos valores de forma asíncrona, 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

Relacionado con: install_keyboard, poll_keyboard, key.


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

Relacionado con: install_keyboard, readkey, clear_keybuf, simulate_keypress.

int readkey();
Devuelve el siguiente caracter del búffer de teclado en formato ASCII. Si el búffer está
vacío espera hasta que se apriete una tecla. El byte de menos peso del valor de retorno
contiene el código 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 código
ASCII sí que le afecta la pulsación de shift y ctrl de la manera normal (shift cambia a
mayúsculas, ctrl+letra da la posición de la tecla en el alfabeto, ej: ctrl+A = 1, ctrl+B = 2,
etc). Apretando alt+key se devuelve sólo el scancode, con el código ASCII cero en el byte
de menor peso. Por ejemplo:
if ((readkey() & 0xff) == 'd') // por código
ASCII
printf("Has pulsado 'd'\n");

if ((readkey() >> 8) == KEY_SPACE) // por código


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 función no puede devolver carácteres mayores que 255. Si necesita leer entradas
Unicode use ureadkey() en vez de readkey()

Relacionado con: install_keyboard, ureadkey, keypressed, clear_keybuf,


simulate_keypress.

int ureadkey(int *scancode);


Devuelve el siguiente caracter del búffer de teclado en formato Unicode. Si el búffer está
vacío 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 función es capaz de devolver carácteres mayores que 255.

Relacionado con: install_keyboard, readkey, keypressed, clear_keybuf,


simulate_ukeypress.

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
parámetro está el mismo formato que el devuelto por readkey().

Relacionado con: install_keyboard, simulate_ukeypress, keypressed, readkey.

void simulate_ukeypress(int key, int scancode);


Introduce una tecla en el búffer de teclado, como si el usuario la hubiese pulsado. El
parámetro está en el mismo formato devuelto por ureadkey()

Relacionado con: install_keyboard, simulate_keypress, keypressed, ureadkey.

extern int (*keyboard_callback)(int key);


Si se activa, esta función es será llamada por el controlador del teclado en respuesta a
cualquier tecla. Se le pasará una copia del valor que se va a añadir al buffer de entrada, y la
función 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
después. Esta rutina se ejecuta en contexto de interrupción, por lo que debe estar bloqueada
(locked) en memoria.

Relacionado con: install_keyboard, readkey, ureadkey, keyboard_ucallback,


keyboard_lowlevel_callback.

extern int (*keyboard_ucallback)(int key, int *scancode);


Versión Unicode de keyboard_callback(). Si se activa, esta función es llamada por el
controlador de teclado en respuesta a cualquier pulsación de tecla. Se le pasa el valor del
caracter y el scancode que serán añadidos al búffer de entrada, puede modificar el valor del
scancode, y devuelve un código 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
interrupción, por lo que debe ser bloqueada (locked) en memoria.

Relacionado con: install_keyboard, readkey, ureadkey, keyboard_callback,


keyboard_lowlevel_callback.

extern void (*keyboard_lowlevel_callback)(int scancode);


Si se, activa esta función 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 más peso desactivado si la tecla ha sido pulsada o activado si
ha sido soltada. Esta rutina se ejecuta en un contexto de interrupción, así que debe estar
bloqueada (locked) en memoria.

Relacionado con: install_keyboard, keyboard_callback, keyboard_ucallback.


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

Relacionado con: install_keyboard, key_led_flag.

void set_keyboard_rate(int delay, int repeat);


Inicializa la frecuendia de repetición del teclado. Los tiempos se dan en milisegundos.
Pasar cero desactivará la repetición de teclas.

Relacionado con: install_keyboard, readkey, ureadkey.

void clear_keybuf();
Limpia el búffer de teclado.

Relacionado con: install_keyboard, keypressed, readkey, ureadkey.

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 combinación
ctrl+alt+del. La mayoría de SSOO multitarea capturarán esta combinación antes de que
llegue al controlador de Allegro, en cuyo caso puede usar la combinación alternativa
ctrl+alt+fin. Si quiere desactivar este comportamiento en su programa ajuste esta variable a
FALSE.

Relacionado con: install_keyboard.

extern int key_led_flag;


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

Relacionado con: install_keyboard, set_leds.

06 Rutinas de Joystick
• calibrate_joystick
• calibrate_joystick_name
• initialise_joystick
• install_joystick
• joy
• load_joystick_data
• num_joysticks
• poll_joystick
• remove_joystick
• save_joystick_data

int install_joystick(int type);


Inicializa el joystick y calibra el valor de la posición central. El parámetro typo debería ser,
normalmente, JOY_TYPE_AUTODETECT, o mirar la documentación específica de la
plataforma para tener una lista de los drivers disponibles. Debe llamar a esta rutina antes de
usar cualquier otra función del joystick, y se debería asegurar que el joystick está en la
posición central en ese momento. Devuelve cero si no ha habido problemas. Tan pronto
como haya instalado el módulo de joystick, ya será capaz de leer el estado de los botones y
la información digital(on/off) de la dirección, que puede ser suficiente para algunos juegos.
Si quiere obtener una entrada totalmente analógica necesitará usar las funciones de
calibrate_joystick() para medir el rango exacto de las entradas: lea más abajo.

Relacionado con: calibrate_joystick_name, poll_joystick, Variables de


configuración estándar, JOY_TYPE_*/DOS, remove_joystick, load_joystick_data,
calibrate_joystick.

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

Relacionado con: install_joystick, allegro_exit.

int poll_joystick();
El joystick no funciona por interrupciones, así que necesitará llamar a esta función una y
otra vez para actualizar los valores globales de posición. Devuelve cero con éxito o un
número negativo si hubo problemas (normalmente porque no había driver de joystick
instalado).

Relacionado con: install_joystick, joy, num_joysticks.

extern int num_joysticks;


Variables globales que indican el número de joysticks activos. Los controlador actuales
soportan un máximo de cuatro dispositivos.

Relacionado con: install_joystick, joy.

extern JOYSTICK_INFO joy[n];


Array global de información de estado del joystick, que es actualizado por la función
poll_joystick(). Sólo el primer elemento num_joysticks tendrá información útil. La
estructura JOYSTICK_INFO está definida así:
typedef struct JOYSTICK_INFO
{
int flags; - estado de este
joystick
int num_sticks; - ¿cuántos
joysticks activos?
int num_buttons; - ¿cuántos botones?
JOYSTICK_STICK_INFO stick[n]; - información de
estado del stick
JOYSTICK_BUTTON_INFO button[n]; - información 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 botón
on/off
char *name; - descripción de
este botón
} JOYSTICK_BUTTON_INFO;
Puede enseñar los nombres de los botones como parte de una pantalla de configuración en
la que el usuario elige qué función desempeñará cada botón en su juego, pero en situaciones
simples puede asumir con seguridad que los dos primeros elementos del array button serán
siempre los controles principales de disparo.

Cada joystick proveerá una o más entradas stick, de varios tipos. Estas pueden ser controles
digitales que tienen siempre un valor específico (ej. un gamepad, el sombrero del
Flightstick Pro o Wingman Extreme, o un joystick normal que todavía no ha sido
calibrado), o pueden ser entradas analógicas con un rango suave de movimiento. Las
palancas pueden tener un número diferente de ejes, por ejemplo un controlador direccional
normal tiene dos, pero el mando de gases del Flightstick Pro sólo 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; - ¿cuántos ejes
tenemos?
JOYSTICK_AXIS_INFO axis[n]; - información de
estado del eje
char *name; - descripción 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 dirección.

La información sobre los ejes del mando está almacenada en la subestructura:


typedef struct JOYSTICK_AXIS_INFO
{
int pos; - posición
analógica del eje
int d1, d2; - posición digital
del eje
char *name; - descripción 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 posición del eje X, el campo pos contendrá la posición
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 poniéndolo a las posiciones
mínima, central y máxima, y emulando los valores d1 y d2 con joysticks analógicos
comparando la posición actual con el punto central.

La variable flags de la estructura joystick puede ser cualquier combinación de los siguientes
bits:

JOYFLAG_DIGITAL
Este control tiene entrada digital.

JOYFLAG_ANALOGUE
Este control tiene entrada analógica.

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 analógica una vez sea calibrado, pero ahora no lo
hace.

JOYFLAG_CALIBRATE
Indica que este control debe ser calibrado. Muchos dispositivos requieren múltiples pasos
de calibración, por lo que puede llamar la función calibrate_joystick() desde un bucle hasta
que este bit desaparezca.

JOYFLAG_SIGNED
Indica que la posición analógica 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 posición analógica 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 permitirán escribir "analog" sin problemas.

Relacionado con: calibrate_joystick_name, install_joystick, poll_joystick,


num_joysticks, calibrate_joystick.

char *calibrate_joystick_name(int n);


Devuelve una descripción textual del siguiente tipo de calibración que será hecha en el
joystick especificado, o NULL si no hace falta más calibración.

Relacionado con: install_joystick, calibrate_joystick, joy, num_joysticks.

int calibrate_joystick(int n);


La mayoría de los joysticks deben ser calibrados antes de poder ser usados de forma
analógica. Esta función realiza la siguiente operación en la serie de calibración 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 podría 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);
}
}
}

Relacionado con: install_joystick, calibrate_joystick_name, joy, num_joysticks.

int save_joystick_data(const char *filename);


Después 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 función
para salvar los datos de calibración del joystick en un fichero de configuración
especificado, que puede ser leído por load_joystick_data(). Pase NULL como filename para
escribir los datos en el fichero de configuración seleccionado actualmente. Devuelve cero si
no hubo problemas.

Relacionado con: load_joystick_data, set_config_file.

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 código de joystick: ni si quiera debe llamar
initialise_joystick() si está usando esta función. Pasa NULL como filename para leer los
datos del fichero de configuración seleccionado actualmente. Devuelve cero si no hubo
problemas: si falla, el estado del joystick queda indefinido y debe reiniciarlo desde el
comienzo.

Relacionado con: install_joystick, save_joystick_data, set_config_file.

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

Relacionado con: install_joystick.

07 Modos gráficos
• destroy_gfx_mode_list
• enable_triple_buffer
• get_display_switch_mode
• get_gfx_mode_list
• get_refresh_rate
• gfx_capabilities
• poll_scroll
• remove_display_switch_callback
• request_refresh_rate
• request_scroll
• request_video_bitmap
• scroll_screen
• set_color_depth
• set_display_switch_callback
• set_display_switch_mode
• set_gfx_mode
• show_video_bitmap

void set_color_depth(int depth);


Especifica el formato gráfico que será usado en las siguientes llamadas a set_gfx_mode() y
create_bitmap(). Las profundidades válidas son 8 (por defecto), 15, 16, 24 y 32 bits.

Relacionado con: set_gfx_mode, set_color_conversion, makecol, getr.

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 serán 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, sólo el driver DOS VESA 3.0, X DGA 2.0 y algunos drivers de DirectX soportan
esta función. La velocidad es especificada en Hz, ej: 60, 70. Para volver a la velocidad por
defecto, pase el valor cero.

Relacionado con: set_gfx_mode, get_refresh_rate.

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

Relacionado con: request_refresh_rate.

GFX_MODE_LIST *get_gfx_mode_list(int card);


Intenta crear una lista de todos los modos de vídeo soportados por un driver gráfico GFX
determinado. Esta función 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 función devuelve NULL, significa que la llamada no tuvo éxito. El puntero mode
apunta a la verdadera lista de modos de vídeo.
typedef struct GFX_MODE {
int width, height, bpp;
} GFX_MODE;
Esta lista termina con un elemento { 0, 0, 0 }.

Relacionado con: destroy_gfx_mode_list, set_gfx_mode, set_color_depth.

void destroy_gfx_mode_list(GFX_MODE_LIST *mode_list);


Borra de la memoria la lista de modos creada por get_gfx_mode_list().

Relacionado con: get_gfx_mode_list, set_gfx_mode, set_color_depth.

int set_gfx_mode(int card, int w, int h, int v_w, int v_h);


Cambia a modo gráfico. El parámetro card normalmente debería ser GFX_AUTODETECT,
GFX_AUTODETECT_FULLSCREEN o GFX_AUTODETECT_WINDOWED, o puede
mirar la documentación específica de su plataforma para tener una lista los drivers
disponibles. Los parámetros w y h especifican que resolución de pantalla quiere.

Los parámetros v_w y v_h especifican el tamaño mínimo de la pantalla virtual, en caso de
que necesite una pantalla virtual grande para hacer scroll por hardware o intercambio de
páginas. Debería ponerlos a cero si no le importa la pantalla virtual. Las pantallas virtuales
crean mucha confusión, pero en realidad son muy simples. Aviso: ahora viene una
explicación condescendiente, por lo que quizás quiera saltarse el resto del párrafo :-)
Imagínese la memoria de vídeo como una pieza rectangular de papel que es vista a través
de un pequeño agujero (su monitor) hecho sobre cartón. Ya que el papel es más grande que
el agujero, sólo puede ver una parte de él cada vez, pero moviendo el cartón puede alterar
qué porción está visualizando. Puede dejar el agujero en una posición e ignorar el resto de
la memoria de vídeo no visible, pero puede conseguir una gran variedad de útiles efectos
desplazando la ventana de visualización, o dibujando en una parte de la memoria de vídeo
no visible, y entonces intercambiar páginas para visualizar la nueva pantalla.

Por ejemplo, puede seleccionar el modo 640x480 en el cual el monitor actúa 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 vídeo. Esta configuración sería así:

(0,0)------------(640,0)----(1024,0)
| | |
| pantalla visible | |
| | |
(0,480)----------(640,480) |
| |
| resto de la memoria de vídeo |
| |
(0,1024)--------------------(1024,1024)
¿Qué es eso? ¿Está viendo esto con una fuente proporcional? Jejeje.

Cuando llama set_gfx_mode(), los parámetros v_w y v_h representan el tamaño mínimo de
la pantalla virtual que es aceptable para su programa. El rango de tamaños posibles es
normalmente muy restringido, y es posible que Allegro acabe creando una pantalla virtual
más 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 tamaños pueden ser y no ser posibles:
no asuma que vayan a funcionar. En modo-X la anchura virtual puede ser cualquier
múltiplo 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).

Después de seleccionar el modo gráfico, los tamaños físicos 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 descripción del problema en allegro_error. De otro modo
devuelve cero.

Como caso especial, si usa el código de driver mágico GFX_SAFE, Allegro garantizará que
el modo siempre será establecido correctamente. Intentará seleccionar la resolución que
pidió, y si falla, usará aquella resolución que sea fiable en la plataforma actual (esto es
modo VGA a 320x200 bajo DOS, una resolución de 640x480 bajo Windows, la resolución
actual del framebuffer bajo Linux si está soportada, etc). Si no puede establecer ningún
modo gráfico de ninguna manera, devolverá un valor negativo indicando que debería
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 gráfico que funcione, y no puede perder el tiempo probando diferentes
resoluciones y haciendo la comprobación de errores. Tenga en cuenta, que tras una llamada
con éxito a set_gfx_mode con este driver, no puede hacer ninguna asunción sobre el ancho
o alto de la pantalla o su profundidad de color: su código deberá tratar con este pequeño
detalle.

Finalmente, GFX_TEXT es otro driver mágico que normalmente cierra cualquier modo
gráfico abierto anteriormente, impidiendo que pueda usar la variable global screen, y en
aquellos entornos que tienen modos de texto, vuelve a ajustar aquél más parecido al activo
antes de Allegro (normalmente 80x25). Con este driver los parámetros de tamaño de
set_gfx_mode no significan nada en absoluto, así que puede dejarlos a cero o cualquier otro
número que prefiera.

Relacionado con: allegro_error, Variables de configuración estándar,


GFX_*/DOS, GFX_*/Windows, GFX_*/X, GFX_*/Linux, GFX_*/BeOS,
set_color_depth, request_refresh_rate, screen, gfx_capabilities.

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 serán soportados
por cada driver gráfico en cada plataforma: debe llamar a esta rutina tras iniciar el modo
gráfico 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 debería usarlo con
cuidado, porque sus usuarios no se impresionarán si quieren cambiar de programa,
¡pero usted no les deja!
• SWITCH_PAUSE
Pone en pausa el programa mientras esté en segundo plano. La ejecución se
restablecerá tan pronto como el usuario vuelva al programa. Este modo está por
defecto en la mayoría 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 vídeo, por lo tanto de la pantalla, y los bitmaps de vídeo que haya
creado se eliminarán después 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 inútil
para implementar algo mejor.
• SWITCH_BACKGROUND
El programa seguirá ejecutándose en background, con la variable screen apuntando
temporalmente a un buffer de memoria en los modos de vídeo a pantalla completa.
Debe tener especial cuidado cuando use este modo, porque ocurrirán cosas malas si
el bitmap de pantalla cambia cuando su programa no lo espera (lea más abajo).
• SWITCH_BACKAMNESIA
Como SWITCH_BACKGROUND, pero este modo no se preocupa por acordarse
del contenido de la memoria de vídeo (vea SWITCH_AMNESIA). De nuevo, es el
único modo soportado por los drivers a pantalla completa de Windows que permite
que su programa siga ejecutándose en segundo plano.

Acuérdese de tener mucho cuidado cuando use rutinas gráficas 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
automático puede no ser suficientemente bueno que funcione mientras el programa se
ejecuta en segundo plano o acaba de de pasar al primer plano.

Relacionado con: set_display_switch_callback, get_display_switch_mode.

int set_display_switch_callback(int dir, void (*cb)());


Instala una función de notificación para el cambio de modo que fue previamente
seleccionado por set_display_switch_mode(). El parámetro 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 función puede devolver -1
si su petición es imposible. Puede instalar diferentes funciones de cambio de modo al
mismo tiempo.

Relacionado con: remove_display_switch_callback, set_display_switch_mode.

void remove_display_switch_callback(void (*cb)());


Elimina una función de notificación que fue previamente instalada mediante
set_display_switch_callback(). Todas las funciones serán eliminadas automáticamente
cuando llame a set_display_switch_mode().

Relacionado con: set_display_switch_callback.

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

Relacionado con: set_display_switch_mode.

extern int gfx_capabilities;


Campo de bits describiendo las capacidades del controlador gráfico y el hardware de video
actuales. Puede contener cualquiera de los siguientes bits:
GFX_CAN_SCROLL:
Indica que la función 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 función enable_triple_buffer() sea capaz de
activarlo.

GFX_HW_CURSOR:
Indica que un puntero de ratón 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 ratón. Tenga en cuenta que no todo cursor gráfico puede ser implementado via
hardware: en particular, VBE/AF sólo soporta imágenes 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 ejecución de su programa, por lo que no debe asumir que este bit será constante durante
largos periodos de tiempo. Sólo le dice si un cursor hardware está siendo usado ahora, y
puede cambiar cuando oculte/enseñe el puntero.

GFX_HW_HLINE:
Indica que la versión opaca normal de la función hline() está implementada usando
aceleración por hardware. Esto incrementará el rendimiento, no sólo de hline(), sino
también de otras funciones que la usen internamente, por ejemplo circlefill(), triangle(), y
floodfill().

GFX_HW_HLINE_XOR:
Indica que la versión XOR de la función hline(), y cualquier otra que la use, estan
implementadas usando aceleración por hardware.

GFX_HW_HLINE_SOLID_PATTERN:
Indica que los modos sólidos y con patrones de la función hline(), y cualquier otra función
que la use, estan implementadas usando aceleración por hardware (lea nota abajo).

GFX_HW_HLINE_COPY_PATTERN:
Indica que el modo copia de patrón de la función hline(), y cualquier otra función que la
use, estan implementadas usando aceleración por hardware (lea nota abajo).

GFX_HW_FILL:
Indica que la versión opaca de las funciones rectfill(), clear_bitmap() y clear_to_color(),
están implementadas usando aceleración por hardware.

GFX_HW_FILL_XOR:
Indica que la versión XOR de la función rectfill() está implementada usando aceleración
por hardware.
GFX_HW_FILL_SOLID_PATTERN:
Indica que los modos sólidos y con patrones de la función rectfill() están implementados
usando aceleración por hardware (lea nota abajo).

GFX_HW_FILL_COPY_PATTERN:
Indica que el modo copia de patrón de la función rectill() está implementado usando
aceleración por hardware (lea nota abajo).

GFX_HW_LINE:
Indica que la versión opaca de las funciones line() y vline() está implementada usando
aceleración por hardware.

GFX_HW_LINE_XOR:
Indica que la versión XOR de las funciónes line() y vline() está implementada usando
aceleración por hardware.

GFX_HW_TRIANGLE:
Indica que la versión opaca de la función triangle() está implementada usando aceleración
por hardware.

GFX_HW_TRIANGLE_XOR:
Indica que la versión XOR de la función triangle() está implementada usando aceleración
por hardware.

GFX_HW_GLYPH:
Indica que la expansión de carácter monocromo (para dibujo de texto) está implementada
usando aceleración hardware.

GFX_HW_VRAM_BLIT:
Indica que hacer un blit desde una parte de la pantalla a otra está implementado usando
aceleración por hardware. Si este bit está activado, hacer blits dentro de la memoria de
vídeo será ciertamente el modo más rápido para enseñar una imagen, por lo que sería útil
almacenar parte de sus gráficos más usados en una posición oculta de la memoria de vídeo.

GFX_HW_VRAM_BLIT_MASKED:
Indica que la rutina masked_blit() es capaz de hacer una copia de una parte de vídeo a otra
usando aceleración por hardware, y que draw_sprite() usará copia por hardware cuando un
sub-bitmap de la pantalla o un bitmap de memoria de vídeo sea la imagen origen. Si este bit
está activado, el copiar desde la memoria de vídeo será casi seguramente el modo más
rápido para visualizar una imagen, por lo que podría ser rentable almacenar algunos de sus
sprites más usados en una porción no visible de la memoria de vídeo.

Aviso: ¡si esta bit no está activado, masked_blit() y draw_sprite() no funcionarán


correctamente cuando los use con la memoria de vídeo como bitmap origen! Sólo puede
usar estas funciones para copiar memoria de vídeo si están soportadas por el hardware.
GFX_HW_MEM_BLIT:
Indica que hacer un blit desde un bitmap de memoria a la pantalla usa aceleración por
hardware.

GFX_HW_MEM_BLIT_MASKED:
Indica que masked_blit() y draw_sprite() usan aceleración por hardware cuando la imagen
fuente es un bitmap de memoria, y la imagen destino es la pantalla física.

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 aceleración incluso si este bit no está activado,
porque los bitmaps de sistema también se pueden beneficiar del blit de memoria normal a la
pantalla. Este bit sólo estará activado si los bitmaps de sistema una aceleración 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() están siendo aceleradas por
hardware cuando la imagen fuente es un bitmap de sistema y el destino es la pantalla física.
Note que puede haber alguna aceleración incluso si este bit no está activado, porque los
bitmaps de sistema también se pueden beneficiar del blit de memoria normal a la pantalla.
Este bit sólo estará activado si los bitmaps de sistema una aceleración mayor que la
proporcionada por GFX_HW_MEM_BLIT_MASKED.

Nota: incluso cuando la información diga que el dibujo con patrón está soportado usando
aceleración por hardware, no será posible para cualquier tamaño de patrón. El controlador
VBE/AF sólo soporta patrones de hasta 8x8 pixels, y usará la versión original no acelerada
por hardware de las rutinas de dibujo siempre que use patrones más grandes.

Nota2: estas características de aceleración por hardware sólo surtirán efecto cuando dibuje
directamente sobre la pantalla física, o un sub-bitmap de ésta. La aceleración por hardware
es útil sobre todo con una configuración de cambio de páginas o triple buffer, y
probablemente no habrá diferencia de rendimiento con el sistema "dibuja en un bitmap de
memoria, entonces cópialo a la pantalla".

Relacionado con: enable_triple_buffer, screen, create_video_bitmap,


scroll_screen, request_scroll, show_mouse.

int enable_triple_buffer();
Si el bit GFX_CAN_TRIPLE_BUFFER de la variable gfx_capabilities no está activado,
puede intentar activarlo llamando esta función. 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.

Relacionado con: gfx_capabilities, timer_simulate_retrace, request_scroll,


request_video_bitmap.
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 gráfico no soporta scroll por hardware
o la pantalla virtual no es lo suficientemente grande. Puede usar esta función para mover la
pantalla por un espacio de pantalla virtual grande, o para hacer un intercambio de páginas
entre dos áreas de pantalla virtual que no estén solapadas. Tenga en cuenta que para dibujar
fuera de la posición 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


mayoría de las implementaciones VESA sólo 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 sincronización 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().

Relacionado con: set_gfx_mode, show_video_bitmap, request_scroll,


request_video_bitmap.

int request_scroll(int x, int y);


Esta función es usada para el triple buffering. Hace una petición de scroll por hardware a la
posición especificada, pero vuelve inmediatamente en vez de esperar un retrazo. El scroll
tendrá lugar durante el siguiente retrazo vertical, pero puede seguir ejecutando su código
mientras y usar la rutina poll_scroll() para detectar cuando ha ocurrido el cambio por scroll
(vea examples/ex3buf.c). El triple buffering sólo es posible en cierto hardware: funcionará
en cualquier resolución 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
número limitado de tarjetas gráficas 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 función devuelve cero si no hubo problemas.

Relacionado con: poll_scroll, request_video_bitmap, gfx_capabilities,


timer_simulate_retrace, scroll_screen.

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

Relacionado con: request_scroll, request_video_bitmap.


int show_video_bitmap(BITMAP *bitmap);
Solicita intercambiar la página de pantalla hardware para visualizar el objeto bitmap de
vídeo especificado, que debe tener el mismo tamaño que la pantalla física, y debe haber
sido obtenido usando la función create_video_bitmap(). Devuelve cero si no hubo
problemas. Esta función esperará un retrazo vertical si su tarjeta de vídeo lo requiere, por lo
que no hace falta que llame vsync() manualmente.

Relacionado con: scroll_screen, create_video_bitmap.

int request_video_bitmap(BITMAP *bitmap);


Esta función se usa con triple buffering. Solicita intercambiar la página de pantalla al objeto
bitmap de vídeo 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 código y usar la rutina poll_scroll() para detectar cuándo ocurre el
intercambio realmente. Triple buffering sólo es posible en determinado hardware: mire los
comentarios de request_scroll(). Devuelve cero si no hubo problemas.

Relacionado con: create_video_bitmap, scroll_screen, poll_scroll, request_scroll,


gfx_capabilities, timer_simulate_retrace.

08 Objetos bitmap
• acquire_bitmap
• acquire_screen
• bitmap_color_depth
• bitmap_mask_color
• create_bitmap
• create_bitmap_ex
• create_sub_bitmap
• create_system_bitmap
• create_video_bitmap
• destroy_bitmap
• is_linear_bitmap
• is_memory_bitmap
• is_planar_bitmap
• is_same_bitmap
• is_screen_bitmap
• is_sub_bitmap
• is_system_bitmap
• is_video_bitmap
• lock_bitmap
• release_bitmap
• release_screen
• screen
• set_clip
Una vez haya seleccionado un modo gráfico, 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 imágenes 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 vídeo de su tarjeta
gráfica.

Por ejemplo, para dibujar un pixel en la pantalla escribiría:

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 cómo obtener acceso directo a la memoria de un bitmap.

Allegro soporta varios tipos diferentes de bitmaps:

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

- Bitmaps de memoria, que están situados en la RAM del sistema y pueden ser usados para
almacenar gráficos 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 también
modificará al bitmap padre. Pueden tener cualquier tamaño 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 más pequeñas, ej: partir una pantalla virtual grande en
múltiples secciones (mire examples/exscroll.c).

- Bitmaps de memoria de vídeo. Estos son creados con la función create_video_bitmap(), y


normalmente son implementados como sub-bitmaps del objeto screen.

- Bitmaps de sistema. Se crean mediante la función create_system_bitmap(), y están a


caballo entre los bitmaps de memoria y los de video. Viven en la memoria de sistema, así
pues no están limitado por la cantidad de ram de video de su tarjeta, pero se guardan en un
formato específico de la plataforma que puede activar una aceleración 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 están disponibles
create_system_bitmap() funcionará idénticamente igual que create_bitmap().

extern BITMAP *screen;


Puntero global a un bitmap, de tamaño VIRTUAL_W x VIRTUAL_H. Esto es creado por
set_gfx_mode(), y representa la memoria de vídeo de su hardware. Sólo una parte de este
bitmap será visible, de tamaño 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 páginas. 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 física, por lo que si quiere dibujar en la
pantalla virtual fuera de este rectángulo, deberá ajustar el área de recorte.

Relacionado con: set_gfx_mode, is_screen_bitmap, create_video_bitmap,


scroll_screen.

BITMAP *create_bitmap(int width, int height);


Crea un bitmap de memoria con tamaño width por height, y devuelve un puntero a él. El
bitmap tendrá el área de recorte activada y ajustada al tamaño total del bitmap. La memoria
de la imagen no será limpiada, por lo que probablemente tendrá basura: debería limpiar el
bitmap antes de usarlo. Esta rutina usa siempre el formato global de profundidad de color
especificado al llamar set_color_depth().

Relacionado con: create_bitmap_ex, create_sub_bitmap, create_video_bitmap,


destroy_bitmap, set_color_depth, is_memory_bitmap.

BITMAP *create_bitmap_ex(int color_depth, int width, int height);


Crea un bitmap de una profundidad de color específica (8, 15, 16, 24 o 32 bits por pixel).

Relacionado con: create_bitmap, create_sub_bitmap, create_video_bitmap,


destroy_bitmap, is_memory_bitmap.

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 tamaño y área de recorte diferentes. Cuando cree un sub-bitmap
de la pantalla en modo-X, la posición x debe ser un múltiplo de cuatro. La anchura y altura
del sub-bitmap pueden extenderse fuera de los bordes del bitmap padre (serán recortados),
pero el punto de origen debe estar en una región del bitmap padre.

Relacionado con: create_bitmap, create_bitmap_ex, destroy_bitmap,


is_sub_bitmap.
BITMAP *create_video_bitmap(int width, int height);
Reserva un bitmap de memoria de vídeo del tamaño especificado, devolviendo un puntero
si funcionó, o NULL si hubo algún error (ej: se has quedado sin memoria vram libre). Esto
puede ser usado para reservar memoria de vídeo oculta para almacenar gráficos preparados
para operaciones aceleradas por hardware, o para crear múltiples páginas de vídeo que
luego pueden ser visualizadas con show_video_bitmap(). Los bitmaps de memoria de vídeo
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 función.

Relacionado con: create_bitmap, create_bitmap_ex, create_sub_bitmap,


destroy_bitmap, screen, show_video_bitmap, gfx_capabilities, is_screen_bitmap.

BITMAP *create_system_bitmap(int width, int height);


Crea un bitmap en memoria de sistema del tamaño especificado, devolviendo un puntero a
él si no hubo problemas o NULL en caso contrario.

Relacionado con: create_bitmap, create_bitmap_ex, create_video_bitmap,


create_sub_bitmap, destroy_bitmap, is_system_bitmap.

void destroy_bitmap(BITMAP *bitmap);


Destruye un bitmap de memoria, sub-bitmap, bitmap de memoria de vídeo o un bitmap de
sistema cuando ya no lo necesite.

Relacionado con: create_bitmap, load_bitmap.

void lock_bitmap(BITMAP *bitmap);


Bajo DOS, fija toda la memoria usada por un bitmap. Normalmente no necesita llamar a
esta función 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).

Relacionado con: set_color_depth, bitmap_mask_color.

int bitmap_mask_color(BITMAP *bmp);


Devuelve el color de máscara 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 máximo, verde a cero).

Relacionado con: MASK_COLOR_8, set_color_depth, bitmap_color_depth.


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 común.

Relacionado con: create_sub_bitmap.

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

Relacionado con: is_planar_bitmap, is_memory_bitmap.

int is_planar_bitmap(BITMAP *bmp);


Devuelve TRUE si bmp es un bitmap de pantalla plano (modo-X o Xtended).

Relacionado con: is_linear_bitmap, is_memory_bitmap.

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 línea de la estructura bitmap, ej: bmp->line[y][x]
= color.

Relacionado con: is_linear_bitmap, is_planar_bitmap.

int is_screen_bitmap(BITMAP *bmp);


Devuelve TRUE si bmp es el bitmap screen, o un sub-bitmap de él.

Relacionado con: screen, create_video_bitmap, create_sub_bitmap.

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.

Relacionado con: screen, create_video_bitmap, create_sub_bitmap.

int is_system_bitmap(BITMAP *bmp);


Devuelve TRUE si bmp es un bitmap de sistema, o un sub-bitmap de uno.

Relacionado con: create_system_bitmap, create_sub_bitmap.

int is_sub_bitmap(BITMAP *bmp);


Devuelve TRUE si bmp es un sub-bitmap.
Relacionado con: create_sub_bitmap.

void acquire_bitmap(BITMAP *bmp);


Bloquea el bitmap de memoria de vídeo especificado antes de dibujar en él. Esto no se
aplica a los bitmaps de memoria, y sólo afecta a algunas plataformas (Windows lo necesita,
DOS no). Estas llamadas no son estrictamente necesarias, porque las rutinas de dibujo
adquirirán el bitmap automáticamente antes de acceder a él, pero bloquear una superficie de
DirectDraw es muy lento, y obtendrá mucho más rendimiento si adquiere la pantalla sólo
una vez antes del inicio de la función de redibujado principal, y la suelta cuando el dibujado
ha concluido completamente. Múltiples llamadas de adquisición serán anidadas, y el bitmap
sólo será liberado cuando el contador de bloqueo sea cero. Tenga cuidado porque los
programas DirectX activan un bloqueo de exclusión 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 temporización,
teclado o cualquier otra rutina no gráfica!

Relacionado con: release_bitmap, acquire_screen, release_screen.

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 número de veces para
que esté verdaderamente desbloqueado.

Relacionado con: acquire_bitmap, acquire_screen, release_screen.

void acquire_screen();
Sinónimo de acquire_bitmap(screen);

Relacionado con: acquire_bitmap, release_bitmap, release_screen.

void release_screen();
Sinónimo de release_bitmap(screen);

Relacionado con: acquire_bitmap, release_bitmap, acquire_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 harán que su programa muera horriblemente
si intenta dibujar fuera de los bordes del bitmap.
09 Cargando imágenes
• load_bitmap
• load_bmp
• load_lbm
• load_pcx
• load_tga
• register_bitmap_file_type
• save_bitmap
• save_bmp
• save_pcx
• save_tga
• set_color_conversion

Aviso: cuando use imágenes truecolor, siempre debe ajustar el modo gráfico antes de cargar
cualquier dato. De otro modo el formato de pixel (RGB o BGR) será desconocido, y el
fichero podría ser convertido erróneamente.

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 debería 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 función soporta ficheros BMP, LBM, PCX y TGA, determinando el
tipo por la extensión del fichero. Si el fichero contiene una imagen truecolor, debe ajustar el
modo de vídeo o llamar set_color_conversion() antes de cargarlo.

Relacionado con: load_bmp, load_lbm, load_pcx, load_tga, destroy_bitmap,


save_bitmap, register_bitmap_file_type, set_color_depth, set_color_conversion.

BITMAP *load_bmp(const char *filename, RGB *pal);


Carga un fichero Windows u OS/2 de 256 colores o 24 bits truecolor.

Relacionado con: load_bitmap.

BITMAP *load_lbm(const char *filename, RGB *pal);


Carga un fichero IFF ILBM/PBM de 256 colores.

Relacionado con: load_bitmap.

BITMAP *load_pcx(const char *filename, RGB *pal);


Carga un fichero PCX de 256 colores o 24 bits truecolor.

Relacionado con: load_bitmap.


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.

Relacionado con: load_bitmap.

int save_bitmap(const char *filename, BITMAP *bmp, const RGB *pal);


Escribe un bitmap en un fichero, usando la paleta especificada, que debería ser un array de
256 estructuras RGB. Devuelve distinto de cero si hubo errores. El formato de salida es
determinado por la extensión del fichero: actualmente esta función 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 más grande de lo esperado, ya que Allegro
suele crear pantallas virtuales más 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);

Relacionado con: save_bmp, save_pcx, save_tga, load_bitmap,


register_bitmap_file_type.

int save_bmp(const char *filename, BITMAP *bmp, RGB *pal);


Escribe un bitmap en un fichero BMP de 256 colores o 24 bits truecolor.

Relacionado con: save_bitmap.

int save_pcx(const char *filename, BITMAP *bmp, RGB *pal);


Escribe un bitmap en un fichero PCX de 256 colores o 24 bits truecolor.

Relacionado con: save_bitmap.

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.

Relacionado con: save_bitmap.

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 imágenes en este formato (cualquier función puede ser NULL).
Relacionado con: load_bitmap, save_bitmap.

void set_color_conversion(int mode);


Especifica cómo convertir imágenes entre diferentes profundidades de color cuando se leen
gráficos desde archivos externos o ficheros de datos. El modo es una máscara de bits
especificando qué tipos de conversión se permiten. Si se activa el bit apropiado, los datos
serán convertidos al formato actual de pixel (seleccionado llamando a la función
set_color_depth()), si nó, se dejarán en el mismo formato que tenían en el fichero, debiendo
entonces convertir manualmente el gráfico antes de poder mostrarlo. El modo por defectos
es la conversión total, así que todas las imágenes se cargarán en el modo apropiado para el
modo de vídeo actual. Los bits válidos 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
gráficos truecolor se conviertan a formato hicolor o modo con paleta, incluyendo la función
blit(), y cualquier rutina de conversión automática que se ejecute cuando lea gráficos del
disco. Esto puede producir resultados visuales más atractivos, pero obviamente es mucho
más lento que una conversión directa.

Si intenta usar bitmaps convertidos con funciones como masked_blit() o draw_sprite(),


debería especificar el bit COLORCONV_KEEP_TRANS. Se asegurará de que las áreas de
máscara del bitmap antes y después de la conversión se mantendrán iguales, convirtiendo
los colores transparentes de un modo a otro y ajustando aquellos colores que tras la
conversión podrían ser reconvertidos en transparentes. Este bit afecta a cualquier llamada
blit() entre formatos de pixel distintos y a cualquier conversión automática.

Relacionado con: makecol15_dither, set_color_depth, load_bitmap, load_datafile,


fixup_datafile.

10 Rutinas de paleta
• _set_color
• black_palette
• default_palette
• desktop_palette
• fade_from
• fade_from_range
• fade_in
• fade_in_range
• fade_interpolate
• fade_out
• fade_out_range
• generate_332_palette
• generate_optimized_palette
• get_color
• get_palette
• get_palette_range
• select_palette
• set_color
• set_palette
• set_palette_range
• unselect_palette
• vsync

Todas las funciones de dibujo de Allegro usan parámetros en enteros para representar
colores. En las resoluciones truecolor estos números codifican el color directamente como
una colección 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 código de Allegro escribe 'palette' como 'pallete'. Esto es
porque los ficheros de cabecera de mi viejo compilador Mark Williams del Atari lo
escribían 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 vídeo no manda datos al
monitor, por lo que puede hacer cosas que de otra forma no podría, como alterar la paleta
sin causar parpadeo (nieve). Sin embargo Allegro esperará automáticamente el retrazo
vertical antes de alterar la paleta o hacer scroll por hardware, por lo que normalmente no
debe preocuparse por esta función.
Relacionado con: set_palette, scroll_screen, timer_simulate_retrace.

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 sincronización con el retrazo, por lo que debería llamar
vsync() antes para evitar problemas de nieve.

Relacionado con: set_palette, get_color, _set_color.

void _set_color(int index, const RGB *p);


Esta es una versión inline de set_color(), que puede usar en la función callback del
simulador de retrazo vertical. Sólo debería 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()
usarán llamadas VESA en estas tarjetas, pero _set_color() no sabrá nada de eso).

Relacionado con: set_color, set_gfx_mode, timer_simulate_retrace.

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 función.

Relacionado con: select_palette, palette_color, set_gfx_mode, set_palette_range,


set_color, get_palette.

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.

Relacionado con: set_palette, get_palette_range.

void get_color(int index, RGB *p);


Recupera la entrada de la paleta especificada.

Relacionado con: get_palette, set_color.

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.

Relacionado con: get_palette_range, get_color, set_palette.

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).
Relacionado con: get_palette, set_palette_range.

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, devolviéndola en el parámetro
output. La posición 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 sólo afecta a los colores desde from hasta to (inclusivos: pase 0 y 255
para interpolar la paleta entera).

Relacionado con: fade_in, fade_out, fade_from.

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 (instantáneo). Esta rutina sólo afecta los colores desde from
hasta to (inclusivos: pase 0 y 255 para fundir la paleta entera).

Relacionado con: fade_from.

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 (instantáneo). Esta rutina sólo afecta los
colores desde from hasta to (inclusivos: pase 0 y 255 para fundir la paleta entera).

Relacionado con: fade_in.

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 (instantáneo). Esta rutina sólo afecta los colores desde
from hasta to (inclusivos: pase 0 y 255 para fundir la paleta entera).

Relacionado con: fade_out.

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 (instantáneo).

Relacionado con: fade_in, fade_out, fade_interpolate, fade_from_range.

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 (instantáneo).
Relacionado con: fade_out, fade_from, fade_interpolate, fade_in_range.

void fade_out(int speed);


Funde gradualmente la paleta actual hasta una pantalla negra. La velocidad va de 1 (lento) a
64 (instantáneo).

Relacionado con: fade_in, fade_from, fade_interpolate, fade_in_range.

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 función set_palette(), para que la conversión use la paleta especificada, pero
sin afectar de ningún modo al hardware de visualización. La paleta antigua es almacenada
en un buffer interno, y puede ser recuperada llamando unselect_palette().

Relacionado con: set_palette, unselect_palette.

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

Relacionado con: 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 función load_bitmap() devuelve esto si el fichero no contiene ninguna paleta (ej.
cuando lee un bitmap truecolor).

Relacionado con: generate_optimized_palette, set_color_depth.

int generate_optimized_palette(BITMAP *bmp, PALETTE pal, const char


rsvd[256]);
Genera una paleta de 256 colores óptima para hacer una versión reducida, en cuanto a
color, de la imagen truecolor especificada. El parámetro rsvd apunta a una tabla que indica
qué colores se le permite modificar a la función: 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 optimización.

Relacionado con: generate_332_palette, set_color_depth.

extern PALETTE default_palette;


La paleta por defecto de la BIOS IBM. Se seleccionará automáticamente cuando active un
nuevo modo gráfico.
Relacionado con: black_palette, desktop_palette.

extern PALETTE black_palette;


Una paleta que contiene colores negros sólidos, usada por las rutinas de fundidos.

Relacionado con: desktop_palette.

extern PALETTE desktop_palette;


La paleta usada por el escritorio de baja resolución del Atari ST. No estoy seguro por qué
esto sigue aquí, excepto porque los programas grabber y test la usan. Es probablemente el
único código heredado del Atari que queda en Allegro, y sería una pena quitarlo :-)

Relacionado con: black_palette.

11 Formatos de pixel truecolor


• geta
• geta32
• geta_depth
• getb
• getb15
• getb16
• getb24
• getb32
• getb8
• getb_depth
• getg
• getg15
• getg16
• getg24
• getg32
• getg8
• getg_depth
• getr
• getr15
• getr16
• getr24
• getr32
• getr8
• getr_depth
• makeacol
• makeacol32
• makeacol_depth
• makecol
• makecol15
• makecol15_dither
• makecol16
• makecol16_dither
• makecol24
• makecol32
• makecol8
• makecol_depth
• MASK_COLOR_15
• MASK_COLOR_16
• MASK_COLOR_24
• MASK_COLOR_32
• MASK_COLOR_8
• palette_color

En los modos de vídeo 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 vídeo 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 sólo 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 más parecido, algo que es muy lento a no ser que haya creado un mapa
RGB (mire abajo).

Relacionado con: makecol, makecol_depth, makecol15_dither, rgb_map,


bestfit_color, set_color_depth.

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 sólamente el formato de 32 bits tiene espacio suficiente para guardar un canal
alfa útil. Debería usar colores en formato RGBA sólamente como entrada para
draw_trans_sprite() o draw_trans_rle_sprite() después de llamar a set_alpha_blender(), en
vez de dibujarlos directamente en la pantalla.
Relacionado con: makeacol, set_alpha_blender, set_write_alpha_blender.

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 vídeo actual, llamando a las
funciones previas makecol de 8, 15, 16, 24, o 32 bits según convenga.

Relacionado con: makeacol, makecol8, makecol_depth, makecol15_dither,


rgb_map, set_color_depth.

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.

Relacionado con: makeacol, makecol, makecol8, makecol15_dither, rgb_map,


set_color_depth.

int makeacol(int r, int g, int b, int a);


int makeacol_depth(int color_depth, int r, int g, int b, int a);
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. Sólo debería 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.

Relacionado con: makecol, makecol_depth, set_alpha_blender,


set_write_alpha_blender.

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 imágenes de truecolor a hicolor.
Aparte de llamar estas funciones diréctamente, el difuminado hicolor puede ser activado
automáticamente al cargar gráficos llamando la función set_color_conversion(), por
ejemplo set_color_conversion(COLORCONV_REDUCE_TRUE_TO_HI |
COLORCONV_DITHER).

Relacionado con: makecol, makecol8, set_color_conversion.

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

Relacionado con: getr, getr_depth, makecol, set_color_depth.

int geta32(int c);


Dado un color en un formato de píxel en 32 bits, esta función extrae el componente alfa (de
0 a 255).

Relacionado con: getr8.

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 vídeo 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 según convenga. La parte alfa sólo tiene sentido para píxels de
32 bits.

Relacionado con: getr8, getr_depth, makecol, set_color_depth.

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 sólo
tiene sentido para píxels de 32 bits.

Relacionado con: getr, getr8, geta32, makecol, set_color_depth.

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 vídeo. 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.

Relacionado con: set_palette, makecol, set_color_depth.

#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 máximo, verde a cero).

Relacionado con: bitmap_mask_color, makecol, draw_sprite, masked_blit.

12 Primitivas de dibujo
• _getpixel
• _getpixel15
• _getpixel16
• _getpixel24
• _getpixel32
• _putpixel
• _putpixel15
• _putpixel16
• _putpixel24
• _putpixel32
• arc
• calc_spline
• circle
• circlefill
• do_arc
• do_circle
• do_ellipse
• do_line
• ellipse
• ellipsefill
• floodfill
• getpixel
• hline
• line
• polygon
• putpixel
• rect
• rectfill
• spline
• triangle
• vline

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 posición especificada del bitmap, usando el modo de dibujo actual y
el área de recorte del bitmap.

Relacionado con: getpixel, _putpixel, drawing_mode.

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 más rápidas porque están implementadas como
funciones de ensamblador en línea para profundidades de color específicas. No funcionarán
en modos gráficos de tipo Modo-X, no soportan áreas de recorte (¡se bloquearán si intenta
dibujar fuera del bitmap!), e ignoran el modo de dibujo.

Relacionado con: putpixel.

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.

Relacionado con: putpixel, _getpixel.

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 más rápidas de getpixel() para profundidades de color específicas. No
funcionarán en modo-X y no soportan áreas de recorte, así que debe estar seguro que el
punto está dentro del bitmap.

Relacionado con: getpixel.


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

Relacionado con: hline, line, drawing_mode.

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

Relacionado con: vline, line, drawing_mode.

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 línea desde el punto (x1, y1) hasta (x2, y2), llamando la
función proc para cada pixel. A ésta función se le pasa una copia del parámetro bmp, la
posición x e y, y el parámetro d, por lo que puede llamar la función putpixel().

Relacionado con: do_circle, do_ellipse, do_arc, line.

void line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
Dibuja una línea en el bitmap, desde (x1, y1) hasta (x2, y2).

Relacionado con: hline, vline, do_line, drawing_mode.

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

Relacionado con: polygon, triangle3d, drawing_mode.

void polygon(BITMAP *bmp, int vertices, int *points, int color);


Dibuja un polígono relleno con un número arbitrario de vértices. Pase el número de vértices
y un array que contenga series de puntos x e y (hasta un total del valor vertices*2).

Relacionado con: triangle, polygon3d, drawing_mode.

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

Relacionado con: rectfill, drawing_mode.

void rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
Dibuja un rectángulo sólido con los dos puntos dados como esquinas opuestas.

Relacionado con: rect, clear_bitmap, drawing_mode.


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 círculo alrededor de (x, y) con el radio r, llamando a la
función proc para cada pixel. A ésta función se le pasa una copia del parámetro bmp, la
posición x e y, y el parámetro d, por lo que puede llamar la función putpixel().

Relacionado con: do_ellipse, do_arc, do_line, circle, circlefill.

void circle(BITMAP *bmp, int x, int y, int radius, int color);


Dibuja un círculo con el centro y radio especificados.

Relacionado con: ellipse, arc, circlefill, do_circle, drawing_mode.

void circlefill(BITMAP *bmp, int x, int y, int radius, int color);


Dibuja un círculo relleno con el centro y radio especificados.

Relacionado con: ellipsefill, circle, do_circle, drawing_mode.

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
función proc por cada pixel. A ésta función se le pasa una copia del parámetro bmp, la
posición x e y, y el parámetro d, por lo que puede llamar la función putpixel().

Relacionado con: do_circle, do_arc, do_line, ellipse, ellipsefill.

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

Relacionado con: circle, arc, ellipsefill, do_ellipse, drawing_mode.

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

Relacionado con: circlefill, ellipse, do_ellipse, drawing_mode.

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 función proc por cada uno de ellos. A ésta se le pasará una copia del parámetro bmp, la
posición x e y, y una copia del parámetro 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 círculo total,
64 un ángulo recto, etc. Cero comienza a la derecha del punto central, y valores mayores
rotan en dirección antihoraria desde ahí.
Relacionado con: do_circle, do_ellipse, do_line, arc.

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 dirección 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 círculo total, 64 un ángulo recto, etc. Cero comienza a la
derecha del punto central, y valores mayores rotan en dirección antihoraria desde ahí.

Relacionado con: circle, ellipse, drawing_mode.

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, almacenándolos 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 guías. 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 líneas p0-p1 y p2-p3 son tangentes de la curva bezier). La forma más fácil de
imaginárselo es pensar que la curva empieza en p0 en la dirección de p1, pero gira de tal
forma que llega a p3 desde la dirección de p2. Además de su rol de primitivas gráficas, las
curvas bezier pueden ser útiles para construir caminos alrededor de una serie de puntos de
control, como en exspline.c.

Relacionado con: spline.

void spline(BITMAP *bmp, int points[8], int color);


Dibuja una curva bezier usando los cuatro puntos de control especificados en el array
points.

Relacionado con: calc_spline, drawing_mode.

void floodfill(BITMAP *bmp, int x, int y, int color);


Rellena un área cerrada, comenzando en el punto (x, y), con el color especificado.

Relacionado con: drawing_mode.

13 Blits y sprites
• blit
• clear
• clear_bitmap
• clear_to_color
• draw_character
• draw_gouraud_sprite
• draw_lit_sprite
• draw_sprite
• draw_sprite_h_flip
• draw_sprite_v_flip
• draw_sprite_vh_flip
• draw_trans_sprite
• masked_blit
• masked_stretch_blit
• pivot_scaled_sprite
• pivot_scaled_sprite_v_flip
• pivot_sprite
• pivot_sprite_v_flip
• rotate_scaled_sprite
• rotate_scaled_sprite_v_flip
• rotate_sprite
• rotate_sprite_v_flip
• stretch_blit
• stretch_sprite

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.

Relacionado con: clear_to_color, clear.

void clear(BITMAP *bitmap);


Un alias de clear_bitmap(), existe para mantener compatibilidad hacia atrás. Está
implementado como una función estática inline. El alias puede ser desactivado definiendo
el símbolo 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>

Relacionado con: clear_bitmap.

void clear_to_color(BITMAP *bitmap, int color);


Limpia el bitmap con el color especificado.

Relacionado con: clear_bitmap.

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 parámetros 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 posición correspondiente en el bitmap destino. Esta rutina respeta el
área de recorte del destino, y también 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).
Debería 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 debería 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 más rápido que desde la memoria hacia la pantalla, siempre y cuando el
origen y el destino estén 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 alineación de planos (es decir: (source_x%4) == (dest_x%4)), entonces se
pueden usar los registros de la VGA para realizar una rápida transferencia de datos. Para
tomar ventaja de esto, en modo-X normalmente se almacenan los gráficos en una parte
oculta de la memoria de vídeo (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 aceleración por
hardware. Esto es extremadamente rápido, por lo que si este bit está activado, sería útil
almacenar parte de sus gráficos más frequentemente usados en una porción oculta de la
memoria de vídeo.

Al contrario que la mayoría de las rutinas gráficas, blit() permite que los bitmaps de origen
y destino sean de diferentes profundidades de color, por lo que se puede usar para convertir
imágenes de un formato de pixel a otro.

Relacionado con: masked_blit, stretch_blit, draw_sprite, gfx_capabilities.

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 aceleración por
hardware. Esto es extremadamente rápido, por lo que si este bit está activado, sería útil
almacenar parte de sus gráficos más frequentemente usados en una porción oculta de la
memoria de vídeo.
Atención: ¡si el bit de aceleración por hardware no está activado, masked_blit() no
funcionará correctamente cuando la imagen origen sea la memoria de vídeo, y el gráfico a
dibujar siempre tiene que ser un bitmap de memoria!

Relacionado con: blit, draw_sprite, bitmap_mask_color.

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 imágenes de tal forma que las áreas de origen y
destino no tienen que tener el mismo tamaño. 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. Además, el origen debe ser un bitmap de memoria
o sub-bitmap, no la pantalla hardware.

Relacionado con: blit, stretch_sprite.

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 están marcados con un 0 en
modos de 256 colores o magenta fara datos en truecolor (rojo y azul al máximo y el verde a
cero). Las regiones origen (source) y destino (destination) no deben solaparse.

Relacionado con: blit, masked_blit, stretch_blit, stretch_sprite.

void draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);


Dibuja una copia del bitmap sprite en el bitmap destino en la posición especificada. Eso es
casi igual que blit(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h), pero usa un modo de
dibujado con máscara 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 aceleración por
hardware. Esto es extremadamente rápido, por lo que si este bit está activado, sería útil
almacenar parte de sus gráficos más frequentemente usados en una porción oculta de la
memoria de vídeo.

Atención: ¡si el bit de aceleración por hardware no está activado, draw_sprite() no


funcionará correctamente cuando la imagen origen sea la memoria de vídeo, y el gráfico a
dibujar siempre tiene que ser un bitmap de memoria!

A pesar de no soportar generalmente gráficos de diferentes profundidades de color, como


caso especial puede usar esta función para dibujar imágenes origen de 256 colores en
bitmaps destino truecolor, por lo que puede usar efectos de paleta en sprites específicos
dentro de un programa truecolor.

Relacionado con: bitmap_mask_color, draw_gouraud_sprite, stretch_sprite,


rotate_sprite, draw_character, draw_rle_sprite, draw_compiled_sprite, masked_blit,
blit, draw_sprite_v_flip, draw_trans_sprite, draw_lit_sprite.

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 imágenes espejo exactas, que no es lo mismo que rotar el sprite (y
además esto es más rápido que la rutina de rotación). El sprite debe ser un bitmap de
memoria.

Relacionado con: draw_sprite, bitmap_mask_color.

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 sólo 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 translúcido
es muy lento si dibuja directamente en la memoria de vídeo, así que siempre que sea posibe
debería 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 imágenes con 8 bits de alfa en un destino en RGBA
de 32 bits, mientras llame antes a set_write_alpha_blender().

Relacionado con: bitmap_mask_color, draw_sprite, draw_lit_sprite,


draw_trans_rle_sprite, color_map, set_trans_blender, set_alpha_blender,
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 sólo se puede usar si
antes ha creado una tabla de colores (para modos de 256 colores) o un mapa de fundido
(para modos truecolor).

Relacionado con: draw_lit_rle_sprite, color_map, set_trans_blender,


bitmap_mask_color, draw_sprite, draw_trans_sprite, draw_gouraud_sprite.

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 sólo se puede usar si antes ha creado una tabla de colores
(para modos de 256 colores) o un mapa de fundido (para modos truecolor).

Relacionado con: bitmap_mask_color, draw_sprite, draw_lit_sprite, color_map,


set_trans_blender.

void draw_character(BITMAP *bmp, BITMAP *sprite, int x, int y, int color);


Dibuja una copia del sprite en el bitmap destino en la posición especificada, dibujando los
pixels transparentes (cero en modos de 256 colores, rosa fucsia en modos truecolor) con el
modo de texto actual (ignorándolos 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.

Relacionado con: draw_sprite, bitmap_mask_color.

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 posición especificada, y entonces será rotado el ángulo especificado sobre su
centro. El ángulo es un número de punto fijo 16.16 con el mismo formato usado por las
funciones trigonométricas de punto fijo, siendo 256 un círculo completo, 64 un ángulo
recto, etc. Todas las funciones de rotación pueden usar diferentes tipos de bitmaps de
origen y destino, incluso bitmaps de pantalla o con una profundidad de color distinta.

Relacionado con: draw_sprite, rotate_scaled_sprite, rotate_sprite_v_flip, itofix,


Trigonometría de punto fijo, pivot_scaled_sprite, pivot_scaled_sprite_v_flip,
pivot_sprite, pivot_sprite_v_flip, rotate_scaled_sprite_v_flip.

void rotate_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle);


Como rotate_sprite, pero también invierte la imágen verticalmente. Para invertir la imagen
horizontalmente, use esta rutina pero añada itofix(128) al ángulo. Para invertir la imágen en
ambos ejes, use rotate_sprite() y añada itofix(128) a su ángulo.

Relacionado con: pivot_sprite_v_flip, pivot_scaled_sprite_v_flip, rotate_sprite,


rotate_scaled_sprite_v_flip.

void rotate_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle,


fixed scale);
Como rotate_sprite(), pero modifica el tamaño de la imagen a la vez que la rota.

Relacionado con: pivot_scaled_sprite, pivot_scaled_sprite_v_flip, rotate_sprite,


rotate_scaled_sprite_v_flip.

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.
Relacionado con: rotate_sprite, rotate_scaled_sprite, rotate_sprite_v_flip.

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.

Relacionado con: rotate_sprite, pivot_scaled_sprite, pivot_sprite_v_flip.

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.

Relacionado con: pivot_sprite, rotate_sprite_v_flip.

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.

Relacionado con: pivot_sprite, pivot_scaled_sprite_v_flip, rotate_sprite,


rotate_scaled_sprite.

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.

Relacionado con: pivot_sprite, pivot_scaled_sprite, rotate_sprite,


rotate_scaled_sprite_v_flip, rotate_sprite_v_flip.

void stretch_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int w, int h);
Dibuja un sprite en el bitmap en la posición especificada, cambiando el tamaño 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 máximo, verde a cero).

Relacionado con: draw_sprite, stretch_blit, bitmap_mask_color.

14 Sprites RLE
• destroy_rle_sprite
• draw_lit_rle_sprite
• draw_rle_sprite
• draw_trans_rle_sprite
• get_rle_sprite

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 imágenes que sólo son copiadas en la pantalla, en vez de pintar en
ellas o usarlas como patrones de relleno, etc. Si este es el caso, sería mejor que usase estas
imágenes 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 sólido. Los sprites
RLE son normalmente más pequeños que los bitmaps, tanto por la compresión run length
como porque evitan la mayoría de sobrecarga de la estructura bitmap. También son
normalmente más rápidos 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
rápidas 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 tamaño. De
hecho, lo único que puede hacer con ellos es copiarlos en un bitmap con la función
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 basándose en el bitmap especificado (que debe ser un bitmap de
memoria).

Relacionado con: draw_sprite, stretch_blit, bitmap_mask_color.

void destroy_rle_sprite(RLE_SPRITE *sprite);


Destruye una estructura de sprite RLE previamente creada por get_rle_sprite().

Relacionado con: 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 posición especificada.

Relacionado con: draw_trans_rle_sprite, draw_lit_rle_sprite, bitmap_mask_color,


get_rle_sprite, draw_sprite, draw_compiled_sprite.
void draw_trans_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, int x, int y);
Versión translúcida de draw_rle_sprite(). Vea la descripción de draw_trans_sprite(). Sólo
debe ser usado después 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.

Relacionado con: draw_rle_sprite, draw_lit_rle_sprite, draw_trans_sprite,


color_map, set_trans_blender, set_alpha_blender, bitmap_mask_color.

void draw_lit_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, int x, y, color);


Versión teñida de draw_rle_sprite(). Lea la descripción de draw_lit_sprite(). Esta sólo debe
usarse después de que haya construído la tabla de color (para modos de 256 colores) o
funciones de fundido (para modos truecolor).

Relacionado con: draw_rle_sprite, draw_trans_rle_sprite, draw_lit_sprite,


color_map, set_trans_blender, bitmap_mask_color.

15 Sprites compilados
• destroy_compiled_sprite
• draw_compiled_sprite
• get_compiled_sprite

Los sprites compilados se almacenan como instrucciones de código máquina que dibujan
una imagen específica sobre un bitmap, usando instrucciones mov con valores de datos
inmediatos. Esto es el método más rápido para dibujar una imagen con máscara: en mi
máquina, dibujar sprites compilados es unas cinco veces más rápido que usando
draw_sprite() con bitmaps normales. Los sprites compilados son grandes, por lo que si hay
poca memoria, debería usar sprites RLE, y lo que puede hacer con ellos esta incluso más
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 basándose 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
parámetro 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.
Relacionado con: draw_compiled_sprite, destroy_compiled_sprite.

void destroy_compiled_sprite(COMPILED_SPRITE *sprite);


Destruye una estructura de un sprite compilado previamente creado por
get_compiled_sprite().

Relacionado con: 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 posición especificada. El sprite debe ser
compilado según el tipo correcto del bitmap (lineal o planar). Esta función 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 más grande de lo que necesite, y usar el centro como su pantalla. De esta forma puede
dibujar por afuera de los bordes sin ningún problema...

Relacionado con: get_compiled_sprite, draw_sprite, draw_rle_sprite,


bitmap_mask_color.

16 Salida de texto
• allegro_404_char
• destroy_font
• font
• text_height
• text_length
• text_mode
• textout
• textout_centre
• textout_justify
• textout_right
• textprintf
• textprintf_centre
• textprintf_justify
• textprintf_right

Allegro proporciona rutinas de salida de texto que funcionan tanto con fuentes monocromo
y color, que pueden contener cualquier número de rangos de carácteres Unicode. El
programa grabber puede crear fuentes desde conjuntos de carácteres dibujados en un
fichero bitmap (mire grabber.txt para más información), y también puede importar ficheros
de fuentes en formato GRX o BIOS. La estructura fuente contiene un número de engaches
(hooks) que pueden usarse para extenderla con su propio código de dibujo: vea la
definición en allegro/text.h para conocer los detalles.

extern FONT *font;


Una fuente simple con un tamaño 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
función contiene los rangos estándar de carácteres ASCII (U+20 a U+7F), Latin-1 (U+A1 a
U+FF) y Latin Extended-A (U+0100 a U+017F).

Relacionado con: textout, textprintf.

extern int allegro_404_char;


Cuando Allegro no puede encontrar el gráfico que necesita una fuente, en su lugar dibujará
el carácter indicado por allegro_404_char. Por defecto éste es el símbolo del acento
circumflejo, '^'.

Relacionado con: font.

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 carácteres serán ajustados al color
#mode. Si mode es negativo, el texto será dibujado de forma transparente (es decir, el fondo
de los carácteres no será alterado). Por defecto este modo es cero.

Relacionado con: textout, textprintf.

void textout(BITMAP *bmp, const FONT *f, const char *s, int x, y, int color);
Escribe la cadena s en el bitmap en la posición 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.

Relacionado con: font, text_mode, textout_centre, textout_right, textout_justify,


textprintf, text_height, text_length.

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.

Relacionado con: textout, textprintf_centre.


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.

Relacionado con: textout, textprintf_right.

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 región 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.

Relacionado con: textout, textprintf_justify.

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

Relacionado con: font, text_mode, textprintf_centre, textprintf_right,


textprintf_justify, textout, text_height, text_length.

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.

Relacionado con: textprintf, textout_centre.

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.

Relacionado con: textprintf, textout_right.

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.

Relacionado con: textprintf, textout_justify.

int text_length(const FONT *f, const unsigned char *str);


Devuelve la longitud (en pixels) de la cadena en la fuente especificada.

Relacionado con: text_height.

int text_height(const FONT *f)


Devuelve la altura (en pixels) de la fuente especificada.
Relacionado con: text_length.

void destroy_font(FONT *f);


Libera la memoria usada por una estructura de fuente.

17 Renderización de polígonos
• clear_scene
• clear_zbuffer
• clip3d
• clip3d_f
• create_scene
• create_sub_zbuffer
• create_zbuffer
• destroy_scene
• destroy_zbuffer
• polygon3d
• polygon3d_f
• quad3d
• quad3d_f
• render_scene
• scene_gap
• scene_polygon3d
• scene_polygon3d_f
• set_zbuffer
• triangle3d
• triangle3d_f

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 polígonos 3d en el bitmap especificado, usando el modo de render especificado. A
diferencia de la función polygon(), estas rutinas no soportan figuras cóncavas o con
intersecciones, y no pueden dibujar sobre bitmaps de pantalla en modo-X ( si quiere
escribir código en modo-X, dibuja en un bitmap de memoria y cópialo a la pantalla). El
ancho y alto del bitmap de la textura debe ser un múltiplo de dos, pero puede ser diferente,
ejemplo: una textura 64x16 está bien, pero una de 17x3 no. El parámetro que cuenta los
vértices (vc) debe ser seguido por un array que contiene el número 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; - posición
fixed u, v; - coordenadas de la textura
int c; - color
} V3D;

typedef struct V3D_f


{
float x, y, z; - posición
float u, v; - coordenadas de la textura
int c; - color
} V3D_f;
El cómo se almacenan los datos de los vértices depende del modo de render:

Los valores x e y especifican la posición del vértice en coordenadas de pantalla 2d.

El valor z sólo es necesario cuando use corrección de perspectiva en las texturas, y


especifica la profundidad del punto usando coordenadas del mundo 3d.

Las coordenadas u y v sólo son necesarias cuando use texturas, y especifican la posición del
punto en el bitmap de la textura que se corresponde con el vértice indicado. El plano de la
textura es un plano infinito con el bitmap repetido sobre toda la superficie, y la imagen del
polígono resultante en este plano rellenará el polígono cuando se dibuje en pantalla.

Nos referimos a pixels en el plano de la textura como texels. Cada texel es un bloque, nó
sólo un punto, y los números enteros de u y v se refieren a la esquina superior izquierda del
texel. Esto tiene varias implicaciones. Si quiere dibujar un polígono 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 vértices son especificados en órden antihorario. La textura será
aplicada perfectamente sobre el polígono. No obstante, note que si ajustamos u=32, la
última columna de texels que se verán en la pantalla serán los que están 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 polígonos juntos que comparten dos vértices
(como las dos partes de una pieza de cartón doblada), y quiere aplicar sobre ellos una
textura contínua, los valores u y v de los vértices que están en la junta serán iguales para
ambos polígonos. Por ejemplo, si ambos son rectangulares, un polígono 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 números con decimales para u y v indicando puntos que están
parcialmente en un texel. Además, dado que el plano de la textura es infinito, puede
especificar valores mayores que el tamaño de la textura. Esto puede ser usado para repetir
la textura varias veces sobre el polígono.

El valor c especifica el color del vértice, y es interpretado de forma diferente por los modos
de render.

El parámetro type especifica el modo de render, y puede ser cualquiera de los siguientes:
POLYTYPE_FLAT:
Un simple polígono con sombreado plano, que toma el color del valor c del primer vértice.
Este tipo de polígono es afectado por la función drawing_mode(), por lo que puede ser
usado para renderizar polígonos transparentes o XOR.

POLYTYPE_GCOL:
Un polígono con un color de sombreado goraud. Los colores de cada vértice son tomados
del valor c, e interpolados a través del polígono. Esto es muy rápido, pero sólo 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 función makecol().

POLYTYPE_GRGB:
Un polígono 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 sólo puede ser usado después de que haya creado una tabla de mapa de
colores. Los colores para cada vértice 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 polígono con textura afín. Esto dibuja la textura a través del polígono con una simple
interpolación 2d lineal, que es rápida pero matemáticamente incorrecta. Puede estar bien si
el polígono es pequeño o plano hacia la cámara, pero como no cuenta con la acortación de
perspectiva, puede producir extraños 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 polígono texturizado con corrección de perspectiva. Esto usa el valor z de la estructura
del vértice así como las coordenadas u/v, por lo que las texturas se ven correctamente
independientemente del ángulo de visualización. Ya que esto envuelve cálculos de división
en al bucle interior de la texturización, este modo es mucho más 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 división 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 función 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 vértice.
¡Esto sólo puede ser usado después 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 translúcidas. Son aplicables todas las reglas generales de dibujado
translúcido. No obstante, estos modos tienen una limitación: sólo funcionan con bitmaps en
memoria o con memoria de vídeo 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 mínimo 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 serán optimizadas usando instrucciones MMX. Si el bit CPU_3DNOW
está activado, las rutinas truecolor PTEX*LIT tomarán ventaja de la extensión 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 sólo usan el valor RGB que
se pasa a set_trans_blender() y hacen la interpolación lineal internamente. Por esta razón,
un nuevo conjundo de funciones de fundido que se pasa a set_blender_mode() es ignorado.

Relacionado con: triangle3d, quad3d, polygon, clip3d, cpu_capabilities.

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 triángulos en 3d, usando las estructuras de vértices 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 más rápido que polygon3d[_f](bmp,
type, tex, 3, v[]).

Relacionado con: polygon3d, quad3d, triangle.

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 cuadriláteros en 3d, usando las estructuras de vértices 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[]);

Relacionado con: polygon3d, triangle3d.

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 polígono dado en vtx. vc es el número de vértices, 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 válidas. Como en el proceso de recorte pueden aparecer nuevos
vértices, el tamaño de vout, vtmp y out debería ser al menos vc * (1.5 ^ n), donde n es el
número de planos de corte (5 o 6), y '^' denota "elevado a la". El frustum (volúmen
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
cámara, con la perspectiva en mente, por lo que esta rutina debería ser llamada despues de
aplicar la matriz de cámara, pero antes de la proyección de perspectiva. La rutina
interpolará correctamente u, v, y c en la estructura de vértices. Sin embargo, esto no está
previsto para GCOL en profundidades de color high/truecolor.

Relacionado con: polygon3d, clip3d.

int clip3d(int type, fixed min_z, fixed max_z, int vc, V3D *vtx[], V3D *vout[], V3D
*vtmp[], int out[]);
Versión de punto fijo de clip3d_f(). Esta función se debería usar con cuidado, dad la
precisión limitada de la aritmética de punto fijo, y las altas posibilidades de errores por
redondeo: el código de punto flotante es mejor en la mayoría de situaciones.

Relacionado con: polygon3d, clip3d_f.

Render con zbuffer


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 más cercano se dibuja, en caso contrario se ignora.

No hace falta ordenar los polígonos. No obstante, sigue siendo útil ignorar los polígonos
que no están de cara a la cámara, ya que así se previene la comparación de muchos
polígonos ocultos contra el Z-buffer. El render mediante Z-buffer es el único algoritmo
soportado por Allegro que resuelve directamente la intersección entre figuras (mire por
ejemplo exzbuf.c). El precio que hay que pagar son unas rutinas más complejas (y más
lentas).
Los polígonos con Z-buffer son por diseño una extensión de los estilos de render normales
POLYTYPE_*. Sólo hay que hacer una OR entre POLYTYPE y el valor
POLYTYPE_ZBUF, y las rutinas normales como polygon3d(), polygon3d_f(), quad3d(),
etc, renderizarán polígonos con Z-buffer.

Ejemplo:

polygon3d(bmp, POLYTYPE_ATEX | POLYTYPE_ZBUF, tex, vc,


vtx);

Por supuesto, las coordenadas z deben ser válidas sin importar el estilo de render.

El procedimiento de render con Z-buffer parece un render con doble buffer. Debería seguir
los siguientes pasos: crear el Z-buffer al comienzo de su programa y hacer que la librería lo
use mediante set_zbuffer(). Entonces, por cada frame, borre el Z-buffer y dibuje polígonos
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 través del conjunto de rutinas
de blending.
• Todas las rutinas con Z-buffer son mucho más 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 tamaño del BITMAP que esté planeando usar para dibujar sus
polígonos. Se pueden definir varios Z-buffers, pero sólo se puede usar uno a la vez, por lo
que debe usar set_zbuffer() para elegir cuál será activo.

Relacionado con: create_sub_zbuffer, set_zbuffer, clear_zbuffer, destroy_zbuffer.

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 tamaño 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 (serán recortados), pero el punto de origen debe estar en una región 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 función
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
tamaño de la pantalla. No necesita crear un z-buffer del tamaño de la pantalla virtual y
entonces un sub-z-buffer de éste.

Relacionado con: create_zbuffer, create_sub_bitmap, destroy_zbuffer.

void set_zbuffer(ZBUFFER *zbuf);


Hace que un Z-buffer sea el activo. Este deberá haber sido creado previamente mediante
create_zbuffer().

Relacionado con: create_zbuffer, clear_zbuffer, destroy_zbuffer.

void clear_zbuffer(ZBUFFER *zbuf, float z);


Escribe z en el Z-buffer (0 significa muy lejos). Esta función 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 polígonos más lejanos de 10, debe
usar: clear_zbuffer(zbuf, 0.1);

Relacionado con: create_zbuffer, set_zbuffer, destroy_zbuffer.

void destroy_zbuffer(ZBUFFER *zbuf);


Destruye el Z-buffer cuando haya finalizado.

Relacionado con: create_zbuffer, set_zbuffer, clear_zbuffer.

Render de escenas
Allegro provee dos métodos simples para quitar caras ocultas:

• Z-buffering - (vea más arriba)


• Algoritmos scan-line - a lo largo de cada línea de su pantalla, mantiene información
sobre el polígono "en el que está" y cuál es el más cercano. Este estado cambia
sólamente cuando la línea cruza el borde de un polígono. Por lo que debe mantener
una lista de bordes y polígonos. 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 sólo dibuja cada pixel una vez. Si tiene muchos polígonos
que se solapan, puede obtener increíbles velocidades comparadas con cualquiera de
los algoritmos previos. Este algoritmo es cubierto por las rutinas *_scene.

El render de escenas sigue los siguientes pasos aproximádamente:

• 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 cámara.
• Recortar polígonos.
• Proyectar con persp_project() o persp_project_f().
• "Dibujar" polígonos con scene_polygon3d() y/o scene_polygon3d_f(). Esto
realmente no dibuja nada, sólo inicializa las táblas.
• Renderizar todos los polígonos definidos previamente en el bitmap con
render_scene().
• Dibujar gráficos no tridimensionales.
• Mostrar el bitmap (blit a la pantalla, cambio de página, etc).

Por cada linea horizontal del área de visualización se usa una lista ordenada de bordes para
saber qué polígonos "están dentro" y cuáles están 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 válidas


para todos los vértices, indiferentemente del estilo de render (en contraste con
polygon3d(), que sólo usa coordenadas z para *PTEX*).
• Todos los polígonos pasados a scene_polygon3d() deben ser proyectados con
perspectiva.
• Tras usar render_scene(), el modo es ajustado a SOLID.

Usar muchos polígonos con máscara reduce el rendimiento, porque cuando se encuentra un
polígono con máscara en primera linea de visión, los polígonos que están detrás deben ser
dibujados también. Lo mismo es aplicable a polígonos FLAT dibujados con
DRAW_MODE_TRANS.

El render con Z-buffer también funciona con el render de escenas. Puede ser útil si tiene
algunos polígonos que se interseccionan, pero la mayoría de los polígonos 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. Además, 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 cuántas aristas y
polígonos renderizará (no puede salirse del límite 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.

Relacionado con: create_zbuffer, scene_polygon3d, render_scene, clear_scene,


destroy_scene, scene_gap.

void clear_scene(BITMAP *bmp);


Inicializa la escena. El bitmap es donde renderizará sus gráficos.

Relacionado con: create_scene, scene_polygon3d, render_scene,


destroy_scene, scene_gap.

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

Relacionado con: create_scene, scene_polygon3d, clear_scene, render_scene,


scene_gap.

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 polígono en la lista de render. Realmente no renderiza nada en este momento.
Debe llamar esta función entre clear_scene() y render_scene().

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

A diferencia de polygon3d(), los polígonos pueden ser cóncavos o estar interseccionados.


Las figuras que penetran en otras pueden salir bien, pero no son manejadas realmente por
este código.

Note que sólo se almacena un puntero a la textura, por lo que debería mantenerla en
memoria hasta render_scene(), donde será usada.

Ya que el estilo FLAT es implementado con la función de bajo nivel hline(), el estilo FLAT
está sujeto a DRAW_MODE. Todos los modos son válidos. Junto con el polígono, el modo
será almacenado para el momento del render, y también 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 elección de la rutina de bajo nivel en ensamblador que será usada por
render_scene() con este polígono.
Devuelve cero con éxito o negativo si no será renderizado debido a que falta la rutina de
render apropiada.

Relacionado con: cpu_capabilities, create_scene, clear_scene, render_scene,


destroy_scene, polygon3d.

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 debería modificar el rectángulo de recorte


del bitmap destino. Por razones de velocidad, debería ajustar el rectángulo de recorte al
mínimo.

Tenga en cuenta también que las texturas pasadas a scene_polygon3d() son almacenadas
como punteros y serán usadas en render_scene().

Relacionado con: create_scene, clear_scene, destroy_scene, scene_gap,


scene_polygon3d.

extern float scene_gap;


Este número (valor por defecto = 100.0) controla el comportamiento del algoritmo de
ordenado en z. Cuando un borde está muy cerca del plano de otro polígono, hay un
intervalo de incertidumbre en el cual no se puede determinar qué objeto es visible (qué z es
más pequeña). Esto es debido a errores numéricos 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 sólo en
1/100 (uno por ciento), serán considerados iguales y el eje x de los planos será usado para
saber qué plano está acercándose mientras nos movemos hacia la derecha.

Valores mayores significan márgenes menores, e incrementan la posibilidad de confundir


planos/bordes realmente adyacentes. Valores menores significan márgenes mayores, e
incrementan la posibilidad de confundir un polígono cercano con uno adyacejte. El valor de
100 está cercano a lo más óptimo. No obstante, el valor optimo oscila con diferentes
resoluciones, y puede ser dependiente de la aplicación. Está aquí para que lo pueda ajustar
al máximo.

Relacionado con: create_scene, clear_scene, destroy_scene, render_scene,


scene_polygon3d.

18 Transparencias y dibujo con patrón


• color_map
• create_blender_table
• create_color_table
• create_light_table
• create_trans_table
• drawing_mode
• set_add_blender
• set_alpha_blender
• set_blender_mode
• set_blender_mode_ex
• set_burn_blender
• set_color_blender
• set_difference_blender
• set_dissolve_blender
• set_dodge_blender
• set_hue_blender
• set_invert_blender
• set_luminance_blender
• set_multiply_blender
• set_saturation_blender
• set_screen_blender
• set_trans_blender
• set_write_alpha_blender
• solid_mode
• xor_mode

void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor);


Ajusta el modo de dibujo gráfico. Esto sólo afecta a las rutinas geométricas como putpixel,
lines, rectangles, circles, polygons, floodfill, etc, y no a la salida de texto, blits o dibujado
de sprites. El modo debería ser uno de los siguientes valores.

DRAW_MODE_SOLID - por defecto, dibujado


sólido
DRAW_MODE_XOR - dibujado or-exclusivo
DRAW_MODE_COPY_PATTERN - rellenado con patrón
multicolor
DRAW_MODE_SOLID_PATTERN - rellenado con patrón de
un solo color
DRAW_MODE_MASKED_PATTERN - rellenado con patrón
enmascarado
DRAW_MODE_TRANS - fundido de color
translúcido
En DRAW_MODE_XOR, los pixels son escritos en el bitmap con una operación 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 más lento que el modo normal.
Con los modos con patrón, usted indica un bitmap de patrón 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 patrón. El ancho y alto del
patrón debe ser un múltiplo de dos, pero pueden ser diferentes, es decir, un patrón de 64x16
está bien, pero uno de 17x3 no. El patrón será repetido en una rejilla comenzando en el
punto (x_anchor, y_anchor). Normalmente debería 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 patrón por la pantalla,
porque la figura se moverá, pero el patrón no, por lo que en algunas situaciones quizás le
interese alterar las posiciones del ancla (anchor).

Cuando selecciona DRAW_MODE_COPY_PATTERN, los pixels simplemente son


copiados del bitmap de patrón 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 más rápido de
los modos con patrón.

En DRAW_MODE_SOLID_PATTERN, cada pixel del patrón es comparado con el color


de máscara (cero en modos de 256 colores, rosa fucsia en modos truecolor). Si el pixel del
patrón es sólido, un pixel del color que pasó a la rutina de dibujado es escrito en el bitmap
destino, de otro modo escribe un cero. El patrón es por esto tratado como una máscara
monocroma, que le permite usar el mismo patrón 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 través 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 imágen existente. Esta sólo debe usarse después de
haber constuído 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 vídeo, así que
siempre que sea posible debería dibujar en bitmaps de memoría.

Relacionado con: xor_mode, solid_mode, color_map, set_trans_blender.

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

Relacionado con: drawing_mode.


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

Relacionado con: drawing_mode.

Transparencia en modos de 256 colores


En modos de vídeo con paleta, la translucidez y la iluminación son implementadas con una
tabla precalculada de 64k, que contiene el resultado de la combinación de cualquier color
c1 con c2. Tiene que crear esta tabla antes de usar cualquiera de las rutinas de iluminación
o translucidez. Dependiendo de cómo 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 combinación. La iluminación 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 sólidos 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 translúcido o iluminado en modos de 256 colores!

Relacionado con: create_color_table, create_light_table, create_trans_table,


set_trans_blender, draw_trans_sprite, draw_lit_sprite, drawing_mode.

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 función, y con niveles de luz intermedios devolverá un color
intermedio. Los valores r,g y b están entre 0-63. Si la función callback no es NULL, se la
llamará 256 veces durante el cálculo, permitiéndole mostrar un indicador de progreso.

Relacionado con: color_map, create_trans_table, create_color_table,


create_blender_table, draw_lit_sprite.
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 sólido). Para una solidez del 50%, pasa 128. Esta función 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 máscara puedan ser dibujados
correctamente. Si la función callback no es NULL, será llamada 256 veces durante el
cálculo, permitiéndole enseñar un indicador de progreso.

Relacionado con: color_map, create_light_table, create_color_table,


draw_trans_sprite.

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 función de fundido para
determinar los resultados de cada combinación 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 debería devolver el
resultado deseado en una estructura RGB con formato 0-63. Entonces Allegro buscará en la
paleta aquél 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 función callback no es NULL, se le llamará
256 veces durante el cálculo, permitiéndole que muestre un indicador de progreso.

Relacionado con: color_map, create_light_table, create_trans_table,


create_blender_table.

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. Después de llamar a set_trans_blender(), set_blender_mode() o
cualquiera de las otras rutinas de modo de fundido, puede usar esta función 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.

Relacionado con: color_map, create_light_table, create_trans_table,


create_color_table, set_trans_blender, set_blender_mode.

Transparencia en truecolor
En los modo de video truecolor, la translucidez y la iluminación están implementadas por
una función de fundido de la forma:

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


Esta rutina toma dos colores como parámetros, los descompone en sus componenetes rojo,
verde y azul, los combina acorde con el valor de interpolación 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 píxels de 15 bits (5.5.5), una para píxels de 16 bits (5.6.5), y
otra para píxels de 24 bits (8.8.8), que puede compartirse entre el código 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 interpolación lineal
simple entre los colores fuente y destino. Cuando se llama a una función de dibujo
translúcido, el parámetro alfa ajustado por esta rutina se usa como factor de interpolación,
que controla la solidez del dibujado (de 0 a 255). Cuando una función de dibujo iluminado
de es llamada, el valor alfa se ignora, y se usa el color pasado a la función 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 función (en un rango de 0 a 255).

Relacionado con: color_map, draw_trans_sprite, draw_lit_sprite, drawing_mode,


set_add_blender, set_burn_blender, set_color_blender, set_blender_mode,
set_alpha_blender, set_write_alpha_blender, set_difference_blender,
set_dissolve_blender, set_dodge_blender, set_hue_blender, set_invert_blender,
set_luminance_blender, set_multiply_blender, set_saturation_blender,
set_screen_blender.

void set_alpha_blender();
Activa el modo de fundido especial de canal-alfa, que se usa para dibujar sprites RGBA de
32 bits. Después de llamar a esta función, 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 tomarán directamente del gráfico origen, asíq 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 debería 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.

Relacionado con: set_trans_blender, draw_trans_sprite, draw_trans_rle_sprite,


set_write_alpha_blender.

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

Relacionado con: set_alpha_blender, draw_trans_sprite, drawing_mode.

void set_add_blender(int r, int g, int b, int a);


Activa un modo de fundido de color para combinar píxels truecolor iluminados o
translúcidos.

Relacionado con: set_trans_blender, drawing_mode.

void set_burn_blender(int r, int g, int b, int a);


Activa un modo de fundido "chamuscado" para combinar píxels truecolor iluminados o
translúcidos. Aquí el brillo de los colores de la imagen origen reduce el brillo de la imagen
destino, oscureciendola.

Relacionado con: set_trans_blender, drawing_mode.

void set_color_blender(int r, int g, int b, int a);


Activa un modo de fundido de color para combinar píxels truecolor iluminados o
translúcidos. Aplica sólo el tono y saturación de la imagen origen a la imagen destino. La
luminosidad de la imagen destino no queda afectada.

Relacionado con: set_trans_blender, drawing_mode.

void set_difference_blender(int r, int g, int b, int a);


Activa el modo de fundido por diferencia para combinar píxels truecolor translúcidos o
iluminados. Esto crea una imágen que tiene colores calculados por la diferencia entre los
colores fuente y destino.

Relacionado con: set_trans_blender, drawing_mode.

void set_dissolve_blender(int r, int g, int b, int a);


Activa un modo de fundido por disolución para combinar píxels truecolor translúcidos o
iluminados. Aleatoriamente, reemplaza los colores de algunos píxels de la imagen destino
con los correspondientes de la imágen origen. El número de pixels reeemplazados depende
del valor alpha (cuanto más alto sea el valor, más pixels se reemplazarán; va pillando la
idea :)

Relacionado con: set_trans_blender, drawing_mode.


void set_dodge_blender(int r, int g, int b, int a);
Activa un mode de fundido "trucado" para combinar píxels truecolor iluminados o
translúcidos. La claridad de colores en la imágen origen ilumina los colores de la imagen
destino. El mayor efecto se consigue con el blanco; el negro no tiene ningún efecto.

Relacionado con: set_trans_blender, drawing_mode.

void set_hue_blender(int r, int g, int b, int a);


Activa un modo de fundido por tono para combinar píxels truecolor iluminados o
translúcidos. Éste aplica el tono del origen al destino.

Relacionado con: set_trans_blender, drawing_mode.

void set_invert_blender(int r, int g, int b, int a);


Activa el modo de fundido inverso para combinar píxels truecolor iluminados o
translúcidos. Funde el color inverso (o negativo) del origen con el de destino.

Relacionado con: set_trans_blender, drawing_mode.

void set_luminance_blender(int r, int g, int b, int a);


Activa el modo de fundido de iluminación para combinar píxels truecolor iluminados o
translúcidos. Aplica la ilumincación del origen al destino. El color de la destinación no
queda afectado.

Relacionado con: set_trans_blender, drawing_mode.

void set_multiply_blender(int r, int g, int b, int a);


Activa un modo de fundido por multiplicación para combinar píxels truecolor iluminados o
translúcidoz. Combina las imágenes origen y destino, multiplicando los coloroes para
producir un color más oscuro. Si el color se multiplica por blanco no cambia; cuando se
multiplica por negro se vuelve negro.

Relacionado con: set_trans_blender, drawing_mode.

void set_saturation_blender(int r, int g, int b, int a);


Activa un modo de fundido de saturación para combinar píxels truecolor iluminados o
translúcidos. Aplica la saturación del origen a la imagen destino.

Relacionado con: set_trans_blender, drawing_mode.

void set_screen_blender(int r, int g, int b, int a);


Activa un modo de fundido de pantalla para combinar píxels truecolor iluminados o
translúcidos. Este modo de fundido ilumina el color de la imagen destino multiplicando el
color inverso del origen con el color destino. Es más o menos el opuesto al modo de
fundido por multiplicación.
Relacionado con: set_trans_blender, drawing_mode.

void set_blender_mode(BLENDER_FUNC b15, b16, b24, int r, g, b, a);


Especifíca un conjunto de rutinas propias de fundido en truecolor, que pueden ser usadas
para implementar cualquier modo de interpolación que necesite. Esta función comparte un
único fundido entre los modos de 24 y 32 bits.

Relacionado con: draw_lit_sprite, drawing_mode, set_blender_mode_ex,


set_trans_blender, color_map, draw_trans_sprite.

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 más completo de rutinas
de fundido. Las rutinas b15, b16, b24 y b32 se usan cuando se vayan a dibujar píxels 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 imágenes RGBA en un
destino que tiene otro formato. Estos fundidos se les pasará un parámetro x de 32 bits, junto
con un valor y de una profundidad diferente de color, y debe hacer algo sensible como
respuesta.

Relacionado con: set_blender_mode, set_alpha_blender.

19 Conversiones de formatos de color


• bestfit_color
• create_rgb_table
• hsv_to_rgb
• rgb_map
• rgb_to_hsv

En general, Allegro está diseñada para usarse sólo con una profundidad de color a la vez,
así que sólo llamará una vez a set_color_depth() y entonces almacenará todos sus bitmaps
en el mismo formato. Si quiere mezclar diferentes formatos de píxel, puede usar
create_bitmap_ex() en vez de create_bitmap(), y llamar a bitmap_color_depth() para pedir
el formato de la imagen en cuestión. La mayoría de las rútinas gráficas requieren que todos
sus parámetros de entrada estén 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 rotación puede copiar entren bitmaps de cualquier formato, convirtiendo los datos
cuando se requiera, draw_sprite() puede dibujar imágenes 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 imágenes de 32 bits RGBA en un destino hicolor o truecolor,
siempre y cuando llame antes a set_alpha_blender(), y la función 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 rápido
(¡obviamente deberá ajustar la paleta de colores correcta antes de la conversión!). Convertir
entre diferentes formatos truecolor es algo más lento, y reducir imágenes truecolor a 256
puede ser muy lento (puede acelerarse si crea una tabla global rgb_map antes de realizar la
conversión).

int bestfit_color(const PALLETE pal, int r, int g, int b);


Busca en la paleta el valor más parecido al color requerido, que es especificado en el
formato hardware de la VGA 0-63. Normalmente debería llamar makecol8() en vez de esto,
pero esta función 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 propósito.

Relacionado con: makecol8.

extern RGB_MAP *rgb_map;


Para acelerar la reducción 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 función 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;

Relacionado con: create_rgb_table, makecol8.

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 función
callback no es NULL, será llamada 256 veces durante el cálculo, permitiéndole enseñar un
indicador de progreso.

Relacionado con: rgb_map.

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 saturación y el valor van de 0 a 1.

20 Acceso directo a la memoria de vídeo


La estructura bitmap es así:
typedef struct BITMAP
{
int w, h; - tamaño del bitmap en pixels
int clip; - no-cero si recortar está
activado
int cl, cr, ct, cb; - límites de recorte izquierdo,
derecho, superior
e inferior
int seg; - segmento para uso con los
punteros a línea
unsigned char *line[]; - punteros al comienzo de cada
línea
} BITMAP;
También hay otras cosas en la estructura, pero podrían cambiar, y no debería usar nada
excepto lo de arriba. El rectángulo de recorte es inclusivo arriba a la izquierda (0 permite
dibujar en la posición 0) pero exclusivo abajo a la derecha (10 permite dibujar en la
posición 9, pero no en la 10). Fíjese 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 más simple sólo servirá si trabaja con bitmaps de memoria (obtenidos con
create_bitmap(), ficheros de datos, y ficheros de imágenes) 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 línea de la imagen. Por ejemplo,
una función 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 línea, 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 también en bitmaps de memoria, necesita usar algunas


macros auxiliares, porque la memoria de vídeo 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 debería reemplazar bmp_write8() por bmp_write16(),
bmp_write24(), o bmp_write32(), y multiplicar el desplazamiento x por el número de bytes
por píxel. 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 más flexible a los bitmaps de memoria, necesita llamar a
las rutinas:

unsigned long bmp_write_line(BITMAP *bmp, int line);


Selecciona la línea de un bitmap en la que va a dibujar.

unsigned long bmp_read_line(BITMAP *bmp, int line);


Selecciona la línea 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. Sólo necesita
llamar a esta función una vez al final de una operación de dibujado, incluso si ha llamado a
bmp_write_line() o bmp_read_line() diversas beces antes.

Estas están implementadas como rutinas de ensamblador en línea, por lo que no son tan
ineficientes como podrían 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 sólo necesita pasar una coordenada y a estas
funciones. Varias posiciones x pueden ser obtenidas simplemente sumando la coordenada x
a la dirección 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 función 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
vídeo los bancos pueden ser seleccionados individualmente, y en otros la memoria de vídeo
es leída y escrita en direcciones diferentes. No obstante, la vida nunca es tan simple como
desearíamos que fuese (esto es verdad incluso cuando _no_ estamos hablando de
programación de gráficos :-) y por supuesto algunas tarjetas de vídeo sólo pueden proveer
un banco. En éstas, las funciones de lectura/escritura se comportarán idénticamente, por lo
que no debería asumir que puede leer de una parte de la memoria de vídeo y escribir en otra
al mismo tiempo. Puede llamar bmp_read_line(), y leer lo que quiera de la línea, entonces
llamar bmp_write_line() con el mismo o diferente valor de línea, y escribir lo que quiera en
ella, pero no debería llamar bmp_read_line() y bmp_write_line() a la vez y esperar poder
leer una línea y escribir en otra simultáneamente. Sería bueno si esto fuese posible, pero si
lo hace, su código no funcionará en tarjetas SVGA de un banco.

Y también está el modo-X. Si nunca antes había programado gráficos en este modo,
probablemente no entienda esto, pero para aquellos que quieren saber cómo Allegro trabaja
con los bitmaps de pantalla del modo-X, aquí va...

Los punteros a línea todavía están presentes, y contienen direcciones lineales, esto es, la
dirección con la cual accedes al primer pixel de la línea. Está garantizada la alineación cada
cuatro pixels de las direcciones, por lo que puede fijar el plano de escritura, dividir su
coordenada entre cuatro, y añadirla al puntero de línea. 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 protección 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 método sólo funcionará con la librería djgpp, cuando
esté usando el modo VGA 13h o un framebuffer lineal!

En su código de inicialización:

#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
• close_fli
• fli_bitmap
• fli_bmp_dirty_from
• fli_bmp_dirty_to
• fli_frame
• fli_pal_dirty_from
• fli_pal_dirty_to
• fli_palette
• fli_timer
• next_fli_frame
• open_fli
• open_memory_fli
• play_fli
• play_memory_fli
• reset_fli_variables

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 están
cargados en la RAM. Aparte de las diferentes fuentes de las que se sacan los datos, estas
dos funciones se comportan de forma idéntica. Ambas dibujan la animación en el bitmap
especificado, que debería ser normalmente screen. Los cuadros se alinearán 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 animación. Si loop está
activado, el reproductor volverá al principio de la animación cuando ésta acabe, de otro
modo, reproducirá la animación una vez. Si la función callback no es NULL, será llamada
por cada frame, permitiéndole 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 animación 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
función callback, si fue ésta la que paró la reproducción. Si necesita distinguir entre
diferentes valores de retorno, su rutina de callback debería devolver enteros positivos, ya
que FLI_OK es cero y FLI_ERROR negativo. Tome nota de que el reproductor FLI sólo
funcionará si se instaló el módulo de temporización, y que alterará la paleta de colores
según la del fichero de animación.

Ocasionalmente podría necesitar un control más detallado sobre la reproducción FLI, por
ejemplo si quiere sobreimprimir algún texto sobre la animación, 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 según
se necesiten.

Relacionado con: play_memory_fli, install_timer, fli_frame.

int play_memory_fli(const void *fli_data, BITMAP *bmp, int loop, int (*callback)());
Reproduce una animación 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 más rápido que desde disco, y es particularmente útil con animaciones FLI
pequeñas que se repiten. Sin embargo, las animaciones pueden fácilmente llegar a ser
grandes, por lo que en la mayoría de los casos sería mejor que use play_fli().

Relacionado con: play_fli, install_timer, fli_frame.

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 información del FLI actual está
almacenada en variables globales, por lo que sólo puede tener una animación abierta a la
vez.

Relacionado con: close_fli, next_fli_frame.

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

Relacionado con: open_fli.

int next_fli_frame(int loop);


Lee el siguiente cuadro de la animación 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 leído y almacenado en las variables
globales fli_bitmap y fli_palette.

Relacionado con: open_fli, fli_bitmap, fli_palette, fli_timer, fli_frame.

extern BITMAP *fli_bitmap;


Contiene el cuadro actual de la animación FLI/FLC.

Relacionado con: next_fli_frame, fli_bmp_dirty_from, fli_palette.

extern PALETTE fli_palette;


Contiene la paleta del FLI actual.

Relacionado con: next_fli_frame, fli_pal_dirty_from, fli_bitmap.

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 líneas 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.

Relacionado con: fli_bitmap, reset_fli_variables.

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

Relacionado con: fli_palette, reset_fli_variables.

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

Relacionado con: fli_bmp_dirty_from, fli_pal_dirty_from.

extern int fli_frame;


Variable global que contiene el número de cuadro actual del fichero FLI. Esto es útil para
sincronizar otros eventos con la animación, por ejemplo podría comprobarla en la función
callback de play_fli() y usarla para reproducir un sample en un punto particular.

Relacionado con: play_fli, play_memory_fli, next_fli_frame.

extern volatile int fli_timer;


Variable global para cronometrar la reproducción FLI. Cuando abre un fichero FLI, una
interrupción 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 enseñar un nuevo cuadro cuando sea mayor que
cero.

Relacionado con: install_timer, next_fli_frame.

22 Rutinas de inicializaión de sonido


• detect_digi_driver
• detect_midi_driver
• install_sound
• remove_sound
• reserve_voices
• set_volume
• set_volume_per_voice

int detect_digi_driver(int driver_id);


Detecta si el dispositivo especificado de sonido digital está disponible. Devuelve el máximo
número de voces que el driver puede proporcionar, o cero si el hardware no está presente.
Esta función debe llamarse _antes_ de install_sound().

Relacionado con: DIGI_*/DOS, DIGI_*/Windows, DIGI_*/Unix, DIGI_*/BeOS,


DIGI_*/QNX, install_sound, reserve_voices.

int detect_midi_driver(int driver_id);


Detecta si el dispositivo especificado de sondo MIDI está disponible. Devuelve el número
máximo 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 debería controlar: si la función
devuelve -1 se trata de un controlador ladrón 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 función debe llamarse _antes_ de install_sound().

Relacionado con: install_sound, reserve_voices, MIDI_*/DOS, MIDI_*/Windows,


MIDI_*/Unix, MIDI_*/BeOS, MIDI_*/QNX.
void reserve_voices(int digi_voices, int midi_voices);
Llame esta función para especificar el número 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() fallarán. Cuántas voces haya disponibles, depende del controlador, y en
algunos casos llegará a reservar más de las deseadas (ejemplo: los controladores de música
sintética FM siempre dan 9 voces en una OPL2 y 18 en una OPL3, y el controlador de
sonido digital de la SB redondeará el número de voces al siguiente valor potencia de dos).
Pase un valor negativo para recuperar los valores por defecto. Debería tener en cuenta, que
la calidad del sonido es inversamente proporcional al número de voces que reserve, por lo
que no reserve más de las que necesite.

Relacionado con: set_volume_per_voice, install_sound, detect_digi_driver,


detect_midi_driver.

void set_volume_per_voice(int scale);


Por defecto, cuando reserva más voces para su driver de sonido digital, Allegro intentará
reducir el volúmen de cada una de ellas para compensarlo. Esto se hace para evitar la
distorsión. Por defecto el volúmen por voz es tal, que si reserva n voces, puede reproducir
hasta n/2 sonidos normalizados centrados sin riesgo de distorsión. La excepción es cuando
tiene menos de 8 voces, ya que el volúmen queda igual que para 8 voces.

Si el sonido resultante es demasiado alto o demasiado bajo, esta función puede ser usada
para ajustar el volúmen de cada voz. Primero debería verificar que sus altavoces están
ajustados a un volúmen razonable, el volúmen global de Allegro ajustado al máximo (mire
set_volume() más abajo), y cualquier otro tipo de mezcladores como el control de volúmen
de Windows están ajustados razonablemente.

Una vez haya determinado que el volúmen de Allegro no es ideal para su aplicación, use
esta función para ajustarlo. Esto debe ser realizado _antes_ de llamara install_sound(). Note
que esta función por ahora sólo es relevante para los drivers que usan el mezclador de
Allegro (la mayoría de ellos).

Si pasa un 0 a esta función, cada sonido centrado será reproducido al máximo volúmen
posible sin distorsión, al igual que los sonidos reproducidos con un driver mono. Los
sonidos en los extremos izquierdo y derecho serán distorsionados si se reproducen al
máximo volúmen. Si quiere reproducir sonidos panoramizados sin distorsión al máximo
volúmen, debe pasar 1 a esta función. Nota: esto es diferente del comportamiento que había
en las WIPs 3.9.34, 3.9.35 y 3.9.36. Si usa esta función con cualquiera de esas versiones,
deberá incrementar su parámetro en uno para obtener el mismo volúmen.

Cada vez que incremente el parámetro en uno, el volúmen de cada voz será reducido a la
mitad. Por ejemplo, si pasa 4, podrá reproducir hasta 16 sonidos centrados con volúmen
máximo sin ninguna distorsión.

Aquí están los valores por defecto, dependiendo del número 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 función no modificará el volúmen que usted especifique mediante
play_sample() o voice_set_volume(). Simplemente alterará la salida global del programa.
Si reproduce sonidos a un volúmen bajo, o si no están nromalizados, podrá reproducir más
sonidos simultáneamente sin distorsión.

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 máximo posible
sin distorsión. Si su volúmen se sale de éste límite, la onda 'dará la vuelta' (los picos serán
valles y viceversa), distorsionando aun más el sonido. Debe tener cuidado para que esto no
ocurra.

Es recomendado que introduzca el valor de este parámetro de forma fija en su programa en


vez de ofrecerlo al usuario. El usuario puede alterar el volúmen con el fichero de
configuración, o puede modificarlo con set_volume().

Para restaurar el volúmen por voz a su comportamiento habitual, pase -1.

Relacionado con: reserve_voices, set_volume, install_sound, detect_digi_driver,


detect_midi_driver.

int install_sound(int digi, int midi, const char *cfg_path);


Inicializa el módulo de sonido. Normalmente debería pasarle DIGI_AUTODETECT y
MIDI_AUTODETECT como los parámetros de controlador, en cuyo caso Allegro leerá la
configuración del hardware del fichero de configuración actual. Esto permite al usuario
seleccionar diferentes valores mediante una utilidad de setup: vea la sección de
configuración para ver los detalles. Alternativamente, veal la documentación específica de
la plataforma para tener una lista de los drivers disponibles. El parámetro cfg_path está
presente sólo por compatibilidad con las versiones anteriores de Allegro, y no tiene ningún
efecto. Devuelve cero si el sonido se instaló correctamente, y -1 si falló. Si falla guardará
una descripción del problema en allegro_error.

Relacionado con: DIGI_*/DOS, DIGI_*/Windows, DIGI_*/Unix, DIGI_*/BeOS,


DIGI_*/QNX, install_sound_input, allegro_error, Variables de configuración
estándar, MIDI_*/DOS, MIDI_*/Windows, MIDI_*/Unix, MIDI_*/BeOS, MIDI_*/QNX,
remove_sound, reserve_voices, detect_digi_driver, detect_midi_driver,
set_volume, play_sample, Control de voces, play_midi, play_audio_stream.

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.

Relacionado con: install_sound, allegro_exit.


void set_volume(int digi_volume, int midi_volume);
Altera el volumen de salida del sonido. Especifique el volumen para la reproducción 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.

Relacionado con: install_sound.

23 Rutinas de samples digitales


• adjust_sample
• allocate_voice
• create_sample
• deallocate_voice
• destroy_sample
• load_sample
• load_voc
• load_wav
• lock_sample
• play_sample
• reallocate_voice
• release_voice
• stop_sample
• voice_check
• voice_get_frequency
• voice_get_pan
• voice_get_position
• voice_get_volume
• voice_ramp_volume
• voice_set_echo
• voice_set_frequency
• voice_set_pan
• voice_set_playmode
• voice_set_position
• voice_set_priority
• voice_set_tremolo
• voice_set_vibrato
• voice_set_volume
• voice_start
• voice_stop
• voice_stop_frequency_sweep
• voice_stop_pan_sweep
• voice_stop_volumeramp
• voice_sweep_frequency
• voice_sweep_pan

SAMPLE *load_sample(const char *filename);


Carga un sample de un fichero, devolviendo un puntero a él, o NULL si hay error.
Actualmente, esta función soporta ficheros WAV mono o estéreo y ficheros VOC mono,
tanto de 8 como 16 bits.

Relacionado con: destroy_sample, load_voc, load_wav, play_sample, Control de


voces.

SAMPLE *load_wav(const char *filename);


Carga un sample de un fichero RIFF WAV.

Relacionado con: load_sample.

SAMPLE *load_voc(const char *filename);


Carga un sample de un fichero VOC de Creative Labs.

Relacionado con: load_sample.

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 definición de la estructura en allegro/digi.h para más
detalles.

Relacionado con: load_sample, destroy_sample.

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.

Relacionado con: load_sample.

void lock_sample(SAMPLE *spl);


Bajo DOS, bloquea toda la memoria usada por el sample. Normalmente no necesita llamar
a esta función porque load_sample() y create_sample() lo harán por usted.

Relacionado con: load_sample, create_sample.

int play_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);
Reproduce un sample con el volumen, panoramización y frecuencia especificados. El
volumen y panoramización van de 0 (min/izquierda) a 255 (máx/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 repetición está activada, el sample será repetido hasta que
llame stop_sample(), y puede ser manipulado mientras es reproducido llamando
adjust_sample().

Relacionado con: install_sound, load_sample, adjust_sample, stop_sample,


Control de voces.

void adjust_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);
Altera los parámetros de un sample mientras es reproducido (útil para manipular sonidos
con repetición). Puede alterar el volumen, la panoramización y frecuencia, y también puede
anular la variable de repetición, 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.

Relacionado con: play_sample.

void stop_sample(const SAMPLE *spl);


Mata un sample, algo necesario si tiene uno en modo repetición. Si hay varias copias del
sample, todas serán paradas.

Relacionado con: play_sample.

Control de voces
Si necesita controlar los samples con más detalle, puede usar las funciones de voz de bajo
nivel en vez de llamar play_sample(). Esto conlleva más trabajo, porque debe reservar y
liberar las voces explícitamente, ya que éstas no se liberan solas al acabar la reproducción,
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 cómo las
voces se reservan
si intenta reproducir más 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 repetición en unidades de sample, por
defecto ajustadas
al comienzo y final del sample.
Relacionado con: install_sound, allocate_voice, deallocate_voice,
reallocate_voice, release_voice, voice_start, voice_set_priority, voice_check,
voice_set_frequency, voice_set_pan, voice_set_position, voice_set_playmode,
voice_set_volume.

int allocate_voice(const SAMPLE *spl);


Reserva una voz de la tarjeta y la prepara para reproducir el sample especificado, ajustando
parámetros por defecto (volumen máximo, panoramización central, sin cambio de
frecuencia, sin loop). Cuando acabe de usar la voz, debe liberarla llamando
deallocate_voice() o release_voice(). Devuelve el número de voz, o -1 si no hay voces
libres.

Relacionado con: Control de voces, deallocate_voice, reallocate_voice,


release_voice, load_sample.

void deallocate_voice(int voice);


Libera una voz de la tarjeta, parando su sonido y liberando los recursos que estuviese
utilizando.

Relacionado con: allocate_voice, voice_stop.

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

Relacionado con: allocate_voice, deallocate_voice, load_sample.

void release_voice(int voice);


Libera una voz, indicando que ya no está interesado en su manipulación. El sonido seguirá
siendo reproducido, y los recursos que usa serán liberados automáticamente cuando acabe
la reproducción. Esto es esencialmente lo mismo que deallocate_voice(), pero espera a que
los sonidos acaben para hacer efecto.

Relacionado con: allocate_voice, deallocate_voice.

void voice_start(int voice);


Activa una voz, usando los parámetros que le haya ajustado.

Relacionado con: Control de voces, allocate_voice, voice_stop, release_voice.

void voice_stop(int voice);


Para una voz, almacenando la posición actual y estado para que luego pueda continuar la
reproducción llamando voice_start().
Relacionado con: voice_start, deallocate_voice, release_voice.

void voice_set_priority(int voice, int priority);


Ajusta la prioridad de una voz (rango 0-255). Esto es usado para decidir qué voces serán
recortadas si intenta usar más de las que puede soportar el controlador de la tarjeta de
sonido.

Relacionado con: Control de voces.

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

Relacionado con: allocate_voice, voice_start, voice_get_position.

int voice_get_position(int voice);


Devuelve la posición actual de la voz, en unidades de sample, o -1 si ha finalizado la
reproducción.

Relacionado con: Control de voces, voice_set_position.

void voice_set_position(int voice, int position);


Ajusta la posición de una voz, en unidades de sample.

Relacionado con: Control de voces, voice_get_position, voice_set_playmode.

void voice_set_playmode(int voice, int playmode);


Ajusta el estado de repetición de una voz. Esto puede hacerse mientras se reproduce la voz,
por lo que puede reproducir un sample con repetición (teniendo el comienzo y final del
loop ajustados correctamente), y entonces borrar la variable de repetición cuando quiera
finalizar el sonido, lo que hará que éste llegue al final del loop, continúe con la siguiente
parte del sample, y acabe de modo normal. El parámetro 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 repetición.
• 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 dirección del sample. Si combina esto con el bit de repetición, 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 combinación con el bit loop, hace que el sample cambie de dirección
cada vez que llega al extremo del bucle, por lo que alterna la dirección de
reproducción.

Relacionado con: Control de voces.

int voice_get_volume(int voice);


Devuelve el volumen de la voz, en el rango 0-255.

Relacionado con: Control de voces, voice_set_volume.

void voice_set_volume(int voice, int volume);


Ajusta el volumen de la voz, en el rango 0-255.

Relacionado con: Control de voces, voice_get_volume, voice_ramp_volume.

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.

Relacionado con: Control de voces, voice_set_volume.

void voice_stop_volumeramp(int voice);


Interrumpe una operación de cambio de volumen.

Relacionado con: voice_ramp_volume.

int voice_get_frequency(int voice);


Devuelve la frecuencia actual en Hz.

Relacionado con: Control de voces, voice_set_frequency.

void voice_set_frequency(int voice, int frequency);


Ajusta la frecuencia de la voz en Hz.

Relacionado con: Control de voces, voice_get_frequency,


voice_sweep_frequency.

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.
Relacionado con: Control de voces, voice_set_frequency.

void voice_stop_frequency_sweep(int voice);


Interrumpe una operación de cambio de frecuencia.

Relacionado con: voice_sweep_frequency.

int voice_get_pan(int voice);


Devuelve la panoramización actual, desde 0 (izquierda) hasta 255 (derecha).

Relacionado con: Control de voces, voice_set_pan.

void voice_set_pan(int voice, int pan);


Ajusta la panoramización, desde 0 (izquierda) hasta 255 (derecho).

Relacionado con: Control de voces, voice_get_pan, voice_sweep_pan.

void voice_sweep_pan(int voice, int time, int endpan);


Comienza una panoramización (movimiento izquierda <;->; derecha) desde la posición
actual hasta la posición endpan, especificando time en milisegundos.

Relacionado con: Control de voces, voice_set_pan.

void voice_stop_pan_sweep(int voice);


Interrumpe una panoramización.

Relacionado con: voice_sweep_pan.

void voice_set_echo(int voice, int strength, int delay);


Ajusta el parámetro de eco para una voz (no implementado actualmente).

Relacionado con: Control de voces.

void voice_set_tremolo(int voice, int rate, int depth);


Ajusta el parámetro de trémolo para una voz (no implementado actualmente).

Relacionado con: Control de voces.

void voice_set_vibrato(int voice, int rate, int depth);


Ajusta el parámetro de vibrado para una voz (no implementado actualmente).

Relacionado con: Control de voces.


24 Rutinas de música MIDI
• destroy_midi
• load_ibk
• load_midi
• load_midi_patches
• lock_midi
• midi_loop_end
• midi_loop_start
• midi_meta_callback
• midi_msg_callback
• midi_out
• midi_pause
• midi_pos
• midi_resume
• midi_seek
• midi_sysex_callback
• play_looped_midi
• play_midi
• stop_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.

Relacionado con: destroy_midi, play_midi.

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.

Relacionado con: load_midi.

void lock_midi(MIDI *midi);


Bajo DOS, bloquea toda la memoria usada por un fichero MIDI. Normalmente no necesita
llamar a esta función porque load_midi() lo hace por usted.

Relacionado con: load_midi.

int play_midi(MIDI *midi, int loop);


Reproduce el fichero MIDI especificado, deteniendo cualquier música anterior. Si la
variable loop está activada, los datos serán repetidos hasta que los sustituya con otra cosa,
de otro modo se parará la música al final del fichero. Pasando un puntero NULL parará
cualquier música 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 :-)

Relacionado con: install_sound, load_midi, play_looped_midi, stop_midi,


midi_pause, midi_seek, midi_pos, midi_msg_callback.

int play_looped_midi(MIDI *midi, int loop_start, int loop_end);


Reproduce un fichero MIDI con una posición 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.

Relacionado con: play_midi, midi_loop_start.

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

Relacionado con: play_midi, midi_pause.

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

Relacionado con: play_midi, stop_midi, midi_resume, midi_seek.

void midi_resume();
Continua la reproducción de un MIDI pausado.

Relacionado con: midi_pause.

int midi_seek(int target);


Avanza hasta la posición 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 posición actual. Devuelve cero si no lo ha conseguido, no-cero si llega al
final del fichero (1 significa que paró la reproducción, 2 significa que volvió a reproducir
desde el principio). Si la función se para porque llegó a EOF, midi_pos contendrá el valor
negativo de la longitud del fichero MIDI.

Relacionado con: play_midi, midi_pos.

void midi_out(unsigned char *data, int length);


Introduce un bloque de comandos MIDI en el reproductor en tiempo real, permitiéndole
activar notas, tocar campanas, etc, sobre el fichero MIDI que esté siendo reproducido.
Relacionado con: install_sound, load_midi_patches, midi_recorder.

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 automáticamente carga todos los datos
requeridos por el fichero MIDI seleccionado, pero debe llamar esto antes de mandar
mensajes de cambio de programa vía comando midi_out(). Devuelve distinto de cero si
ocurrió un fallo.

Relacionado con: install_sound, midi_out.

extern volatile long midi_pos;


Contiene la posición actual (número de beat) del fichero MIDI, o un número negativo si no
se está reproduciendo ninguna música. Util para sincronizar animaciones con la música, y
para comprobar si un fichero MIDI se ha acabado de reproducir.

Relacionado con: play_midi, midi_msg_callback.

extern long midi_loop_start;


extern long midi_loop_end;
Los puntos de comienzo y final del bucle, ajustados por la función play_looped_midi().
Estos pueden ser alterados mientras suena la música, pero debería estar seguro de ponerlos
a valores sensatos (comienzo < final). Si está cambiando ambos al mismo tiempo,
asegúrese de alterarlos en el mismo orden en caso de que una interrupción midi ocurra entre
sus dos cambios. Si los valores están a -1, representan el comienzo y final del fichero
respectivamente.

Relacionado con: play_looped_midi.

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 serán llamadas por cada mensaje
MIDI, meta-evento, y bloque de datos exclusivo del sistema respectivamente. Estas
funciones serán ejecutadas en un contexto de control de interrupción, por lo que todo el
código y datos que usen debería 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 más tarde en su código principal.

Relacionado con: play_midi.

int load_ibk(char *filename, int drums);


Lee una definición de un fichero patch .IBK usado por el controlador Adlib. Si los
tambores están activados, lo cargará como un patch de percusión, de otro modo
reemplazará el conjunto de instrumentos MIDI General. Puede llamar esto antes o después
de iniciar el código de sonido, o simplemente puede activar las variables ibk_file e
ibk_drum_file en el fichero de configuración para cargar los datos automáticamente. ¡Fíjese
que esta función no tiene ningún efecto en otros controladores que no sean Adlib!

Relacionado con: install_sound.

25 Rutinas de flujo de sonido


• free_audio_stream_buffer
• get_audio_stream_buffer
• play_audio_stream
• stop_audio_stream

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 según 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 función crea un nuevo flujo de audio y empieza a reproducirlo. El parámetro len es el
tamaño de cada búffer de transferencia (en samples), que normalmente debería ser una
potencia de 2 y cercana a 1k: búffers más grandes son más eficientes y requieren menos
actualizaciones, pero hay un desfase mayor entre los datos que usted porporciona y los que
se están 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 reproducción de samples. Si quiere ajustar la frecuencia, el volumen
o la panoramización del flujo una vez se esté reproduciendo, puede usar las funciones
normales voice_*() con stream->;voice como un parámetro. Los datos del sample estan
siempre en formato sin signo, con formas de onda en estéreo que consisten en samples
alternativos izquierda/derecha.

Relacionado con: install_sound, get_audio_stream_buffer, stop_audio_stream.

void stop_audio_stream(AUDIOSTREAM *stream);


Destruye un flujo de audio cuando no lo necesite más.

Relacionado con: play_audio_stream.

void *get_audio_stream_buffer(AUDIOSTREAM *stream);


Debe llamar este función a intervalos regulares mientras el flujo de audio está siendo
reproducido, para proveer el siguiente buffer de datos del sample (cuanto más pequeño sea
el tamaño del buffer del flujo, más frecuentemente debe llamar esta función). Si devuelve
NULL, el flujo todavía está reproduciendo los datos y no debe hacer nada. Si devuelve un
valor, esa es la localización del próximo buffer a tocar, y debería cargar el número
apropiado de samples (tantos como especificó al crear el flujo) a esa dirección, por ejemplo
usando un fread() de un fichero. Después de llenar el buffer con datos, llame
free_audio_stream_buffer() para indicar que los datos nuevos ahora son válidos. Fíjese que
esta función no debería ser llamada desde una función de temporizador.

Relacionado con: play_audio_stream, free_audio_stream_buffer.

void free_audio_stream_buffer(AUDIOSTREAM *stream);


Llame esta función después de que get_audio_stream_buffer() devuelva una dirección que
no sea NULL, para indicar que ya ha cargado un nuevo bloque de samples en esa dirección
y que los datos están listos para ser reproducidos.

Relacionado con: get_audio_stream_buffer.

26 Rutinas de grabación de sonido


• digi_recorder
• get_sound_input_cap_bits
• get_sound_input_cap_parm
• get_sound_input_cap_rate
• get_sound_input_cap_stereo
• install_sound_input
• midi_recorder
• read_sound_input
• remove_sound_input
• set_sound_input_source
• start_sound_input
• stop_sound_input

int install_sound_input(int digi_card, int midi_card);


Inicializa el módulo de grabación de sonido, devolviendo cero si no hubo problemas. Debe
instalar el sistema normal de reproducción de sonido antes de llamar esta rutina. Los dos
parámetros de tarjetas deben ser los mismos que en install_sound(), incluyendo
DIGI_NONE y MIDI_NONE para desactivar partes del módulo, o DIGI_AUTODETECT
y MIDI_AUTODETECT para adivinar el hardware.

Relacionado con: DIGI_*/DOS, DIGI_*/Windows, DIGI_*/Unix, DIGI_*/BeOS,


DIGI_*/QNX, install_sound, start_sound_input, midi_recorder, MIDI_*/DOS,
MIDI_*/Windows, MIDI_*/Unix, MIDI_*/BeOS, MIDI_*/QNX, Variables de
configuración estándar.
void remove_sound_input();
Desactiva el módulo cuando haya acabado de usarlo. Normalmente no debe llamar esta
función, porque remove_sound() y/o allegro_exit() lo harán por usted.

Relacionado con: install_sound_input, remove_sound, allegro_exit.

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 dieciséis bits soportada
24 = entrada de audio de ocho y dieciséis bits
soportada

Relacionado con: get_sound_input_cap_stereo, start_sound_input,


get_sound_input_cap_parm, get_sound_input_cap_rate.

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

Relacionado con: get_sound_input_cap_rate, start_sound_input,


get_sound_input_cap_parm, get_sound_input_cap_bits.

int get_sound_input_cap_rate(int bits, int stereo);


Devuelve la frecuencia de grabación de samples máxima posible en el formato
especificado, o cero si los ajustes no son soportados.

Relacionado con: get_sound_input_cap_stereo, start_sound_input,


get_sound_input_cap_parm, get_sound_input_cap_bits.

int get_sound_input_cap_parm(int rate, int bits, int stereo);


Comprueba si la frecuencia de grabación especificada, número de bits y mono/estéreo 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 = razón de muestreo no soportada, pero la razón 'n'
puede funcionar

Relacionado con: get_sound_input_cap_stereo, start_sound_input,


get_sound_input_cap_bits, get_sound_input_cap_rate.

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 selección de entrada. El parámetro debe ser uno
de los valores:
SOUND_INPUT_MIC
SOUND_INPUT_LINE
SOUND_INPUT_CD

Relacionado con: start_sound_input.

int start_sound_input(int rate, int bits, int stereo);


Comienza a grabar en el formato especificado, suspendiendo la reproducción de sonidos si
es necesario (esto sucederá siempre con los controladores actuales). Devuelve el tamaño del
buffer en bytes si hubo éxito, o cero si hubo algún error.

Relacionado con: digi_recorder, set_sound_input_source,


get_sound_input_cap_parm, get_sound_input_cap_bits,
get_sound_input_cap_rate, get_sound_input_cap_stereo, install_sound_input,
read_sound_input, stop_sound_input.

void stop_sound_input();
Para la grabación, ajustando la tarjeta de vuelta al modo normal de reproducción.

Relacionado con: start_sound_input.

int read_sound_input(void *buffer);


Recupera el buffer de audio grabado más reciente en el lugar especificado, devolviendo no-
cero si el buffer ha sido copiado, o cero si todavía no hay nuevos datos disponibles. El
tamaño del buffer puede ser obtenido comprobando el valor de retorno de
start_sound_input(). Debe llamar esta función a intervalos regulares durante la grabación
(típicamente unas 100 veces por segundo), o podría perder datos. Si no puede hacer esto lo
suficientemente rápido, use la función callback digi_recorder() para almacenar la onda de
sonido en un buffer más grande que haya creado antes. Nota: muchas tarjetas de sonido
reproducen un click o sonido raro cuando alternan entre los modos de grabación y
reproducción, por lo que es buena idea descartar el primer buffer después de comenzar la
grabación. La onda siempre se almacena en formato sin signo, con los datos estéreo siendo
samples alternados izquierda/derecha.

Relacionado con: start_sound_input.

extern void (*digi_recorder)();


Si está activada, esta función 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 interrupción, por lo que debe ejecutarse muy rápidamente, el código y la
memoria que modifica debe estar bloqueada (locked), y no puede llamar desde ella rutinas
de sistema o acceder a ficheros del disco.
Relacionado con: install_sound_input, start_sound_input.

extern void (*midi_recorder)(unsigned char data);


Si está activada, esta función es llamada por el controlador de entrada MIDI siempre que un
nuevo byte de datos MIDI esté disponible. Se ejecuta en contexto de interrupción, por lo
que debe ser muy rápida y su código/datos deben estar bloqueados (locked).

Relacionado con: install_sound_input, midi_out.

27 Rutinas de ficheros y compresión


• al_findclose
• al_findfirst
• al_findnext
• append_filename
• delete_file
• exists
• file_exists
• file_size
• file_time
• find_allegro_resource
• fix_filename_case
• fix_filename_path
• fix_filename_slashes
• for_each_file
• get_executable_name
• get_extension
• get_filename
• pack_fclose
• pack_fclose_chunk
• pack_feof
• pack_ferror
• pack_fgets
• pack_fopen
• pack_fopen_chunk
• pack_fputs
• pack_fread
• pack_fseek
• pack_fwrite
• pack_getc
• pack_igetl
• pack_igetw
• pack_iputl
• pack_iputw
• pack_mgetl
• pack_mgetw
• pack_mputl
• pack_mputw
• pack_putc
• packfile_password
• put_backslash
• replace_extension
• replace_filename

Las siguientes rutinas implementan un sistema de ficheros I/O con buffer rápido, 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 descompresión es muy rápida 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_* están 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 código no compilará en otras plataformas. Los bits FA_SYSTEM,
FA_LABEL y FA_ARCH sólo son útiles bajo DOS/Windows (entradas con el bit de
sistema, archivo y etiquetas de volúmen). FA_RDONLY es para directorios con el bit de
sólo 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 parámetro 'attrib', representan un
superconjunto de los bits que debe tener un fichero para ser incluído en la búsqueda. Esto
es, para que un fichero encaje con el patrón, sus atributos pueden contener cualquiera de los
bits especificados, pero no debe contener ningúno de los bits no especificados. Por lo tanto,
si usa 'FA_DIREC | FA_RDONLY', los ficheros y directorios normales serán incluídos
junto con los ficheros y directorios de sólo lectura, pero no los ficheros y directorios
ocultos. Similarmente, si usa 'FA_ARCH' entonces tanto los ficheros archivados como no
archivados serán incluídos.

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 serán todo mayúsculas. Devuelve una copia del parámetro de camino.
Relacionado con: fix_filename_slashes, fix_filename_path.

char *fix_filename_slashes(char *path);


Convierte los separadores de directorios de un nombre de fichero a un carácter estándar. En
plataformas DOS, esto es la antibarra. Devuelve una copia del parámetro de camino.

Relacionado con: fix_filename_case, fix_filename_path.

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
máximo el número de bytes especificados. Devuelve una copia del parámetro dest.

Relacionado con: fix_filename_case, fix_filename_slashes.

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 máximo el número de bytes especificados. Devuelve una copia
del parámetro dest.

Relacionado con: get_filename, replace_extension, append_filename.

char *replace_extension(char *dest, const char *filename, const char *ext, int size);
Sustituye el nombre de fichero+extensión especificados con una nueva extensión,
escribiendo en dest como máximo el número de bytes especificados. Devuelve una copia
del parámetro dest.

Relacionado con: get_extension, replace_filename.

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 máximo el número de bytes especificados. Devuelve una copia del parámetro
dest.

Relacionado con: replace_filename.

char *get_filename(const char *path);


Cuando se le pasa el path específico de un fichero, devuelve un puntero a la porción del
nombre del fichero. Tanto '\' como '/' son reconocidos como separadores de directorios.

Relacionado con: get_extension, put_backslash, replace_filename.

char *get_extension(const char *filename);


Cuando se le pasa un nombre de fichero completo (con o sin información de path) devuelve
un puntero a la extensión del fichero.
Relacionado con: get_filename, put_backslash, replace_extension.

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 función, está anticuado.

Relacionado con: get_extension, get_filename.

int file_exists(const char *filename, int attrib, int *aret);


Chequea la existencia de un fichero de nombre y atributos dados (lea más 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 código de error de
sistema será almacenado en errno.

Relacionado con: exists, file_size, file_time.

int exists(const char *filename);


Versión reducida de file_exists(), que comprueba la existencia de ficheros normales, los
cuales pueden tener los bits de archivo o sólo lectura activados, pero no son ocultos,
directorios, ficheros de sistema, etc.

Relacionado con: file_exists, file_size, file_time.

long file_size(const char *filename);


Devuelve el tamaño del fichero en bytes. Si el fichero no existe u ocurre un error, devolverá
cero y almacenará el código de error de sistema en errno.

Relacionado con: file_exists, file_time.

time_t file_time(const char *filename);


Devuelve el tiempo de modificación de un fichero (número de segundos desde las 00:00:00
GMT del 1 de Enero de 1970).

Relacionado con: file_exists, file_size.

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 máscara (ej: *.exe) y atributos
especificados (lea más arriba), y ejecuta callback() por cada uno de ellos. A callback() se le
pasan tres parámetros, el primero es la cadena que contiene el nombre completo del fichero,
el segundo los atributos del fichero, y el tercer parámetro es un entero que es copia de
param (puede usar esto para lo que quiera). Si ocurre un error, el código de error será
almacenado en errno, y callback() puede abortar for_each_file al activar errno. Devuelve el
número de llamadas con éxito hechas a callback().

int al_findfirst(const char *pattern, struct al_ffblk *info, int attrib);


Función de bajo nivel para buscar ficheros. Esta función busca el primer fichero que
concuerde con el patrón y los atributos de fichero especificados (lea más arriba). La
información sobre el fichero (si existe) será puesta en la estructura al_ffblk que debe
proveer usted. La función 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 modificación del
fichero
long size; - tamaño del fichero
char name[512]; - nombre del fichero
};
Hay más cosas en esta estructura, pero son para uso interno.

Relacionado con: al_findnext, al_findclose.

int al_findnext(struct al_ffblk *info);


Esto encuentra el siguiente fichero en una búsqueda 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.

Relacionado con: al_findfirst, al_findclose.

void al_findclose(struct al_ffblk *info);


Esto cierra una búsqueda previamente abierta mediante al_findfirst().

Relacionado con: al_findfirst, al_findnext.

int find_allegro_resource(char *dest, const char *resource, const char *ext, const char
*datafile, const char *objectname, const char *envvar, const char *subdir, int size);
Busca un archivo de recursos, ej allegro.cfg o language.dat. Pasándole una cadena resource
describiendo qué se está buscando, junto con una información extra opcional como la
extensión por defecto, en qué datafile mirar, qué nombre de objeto debería tener en el
datafile, cualquier variable de entorno que se tenga que chequear, y cualquier subdirectorio
que le gustaría comprobar, así como la localización por defecto, esta función 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 parámetro dest.
void packfile_password(const char *password);
Activa el password de encriptación que será usado para todas las operaciones de
lectura/escritura con ficheros abiertos en el futuro con las funciones packfile de Allegro
(estén comprimidos o nó), incluyendo las rutinas de configuración, salvado y cargado. Los
ficheros escritos con un password no pueden ser leídos 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 vacía para volver al modo normal, no encriptado. Si está usando
esta función 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", sería muy fácil acceder a sus datos :-)

Importante: tan pronto como haya abierto un fichero usando un password de encriptación,
llame a packfile_password(NULL). Mejor aún, no use esta función. Nunca.

Relacionado con: pack_fopen, load_datafile.

PACKFILE *pack_fopen(const char *filename, const char *mode);


Abre un fichero según 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 serán comprimidos a medida que
se escriben en el fichero, y automáticamente descomprimidos durante las
operaciones de lectura. Los ficheros creados de este modo producirán basura si se
intentan leer sin activar antes este modo.
• '!' - abrir fichero para escribir en modo normal, sin compresión, pero añade 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 parámetro de
modo. Si todo funciona, pack_fopen() devuelve un puntero a una estructura de fichero, y
con error, devuelve NULL y almacena el código de error en errno. Un intento de leer un
fichero normal en modo comprimido activará errno a EDOM.

Las funciones de ficheros también entienden varios nombres "mágicos" que pueden ser
usados por varios motivos. Estos nombres son:

• "#" - lee datos que han sido añadidos al fichero ejecutable con la utilidad exedat,
como si fuesen de un fichero independiente.
• 'nombre.dat#nombre_obj' - abre un objeto específico de un fichero de datos, y lo lee
como si fuese de un fichero normal. Puede crear ficheros de datos anidados
exáctamente como una estructura normal de directorios, por ejemplo podría abrir el
fichero 'nombre.dat#graficos/nivel1/datomapa'.
• '#nombre_obj' - combinación de lo de arriba, leer un objeto de un fichero de datos
que ha sido añadido al ejecutable.

Con estos nombres especiales, los contenidos de un objeto de un fichero de datos o de un


fichero añadido pueden ser leídos de modo idéntico 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: sólo pueden ser leídos. Además, debe tener su fichero de datos descomprimido o
con compresión por objetos si planea leer objetos individuales (de otra manera, habrá una
sobrecarga de búsqueda al ser leído). 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 específico 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, debería importarla como un bloque binario en vez de un
objeto BITMAP.

Relacionado con: file_select, packfile functions, pack_fopen_chunk,


packfile_password.

packfile functions
Relacionado con: pack_fopen.

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 sólo parámetro de tamaño en vez de ese estúpido sistema de
tamaño y num_elements, sólo puede avanzar en un fichero hacia delante desde la posición
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 búsqueda es muy lenta
cuando lea ficheros comprimidos, y que debería 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 código de
ficheros de datos, pero pueden serle útiles para sus propias rutinas de ficheros. Un chunk
provee una vista lógica de parte de un fichero, que puede ser comprimido como un ente
individual y será automáticamente insertado y comprobará los contadores de tamaño para
prevenir la lectura después del final del chunk. Para escribir un chunk en un fichero f, use
este código:

/* 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 serán precedidos con dos contadores de tamaño (32 bits, big-
endian). Para los chunks sin compresión, éstos serán ajustados al tamaño de los datos del
chunk. Para chunks comprimidos (creados al activar la variable pack), el primer tamaño es
el tamaño real del chunk, y el segundo será el tamaño negativo de los datos
descomprimidos.

Para leer el chunk, use este código:

/* 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 tamaño creados cuando el chunk fue escrito, y
automáticamente descomprimirá el contenido del chunk si fue comprimido. El tamaño
también evitará leer después del final del chunk (Allegro devolverá EOF si intenta esto), y
automáticamente ignora los datos no leídos 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 compresión es heredado del
fichero padre, por lo que sólo 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.
Relacionado con: pack_fclose_chunk, pack_fopen.

PACKFILE *pack_fclose_chunk(PACKFILE *f);


Cierra un sub-chunk de un fichero, que previamente ha sido obtenido al llamar
pack_fopen_chunk().

Relacionado con: pack_fopen_chunk.

28 Rutinas de ficheros de datos


• find_datafile_object
• fixup_datafile
• get_datafile_property
• load_datafile
• load_datafile_callback
• load_datafile_object
• register_datafile_object
• unload_datafile
• unload_datafile_object

Los ficheros de datos son creados por la utilidad grabber, y tienen la extensión .dat. Pueden
contener bitmaps, paletas de color, fuentes, sonidos, música MIDI, animaciones FLI/FLC y
cualquier otro tipo binario de datos que importe.

Atención: cuando use imágenes truecolor, debería activar el modo gráfico antes de cargar
ningún bitmap! Si no, el formato (RGB o BGR) será desconocido, y el fichero
probablemente será convertido erróneamente.

Mire la documentación en pack_fopen() para obtener información 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 función
packfile_password() para introducir la clave correcta. Mire grabber.txt para mas
información. Si el fichero de datos contiene gráficos truecolor, debe entrar en modo gráfico
o llamar set_color_conversion() antes de cargarlo.

Relacionado con: find_datafile_object, register_datafile_object,


load_datafile_callback, unload_datafile, load_datafile_object, set_color_conversion,
fixup_datafile, packfile_password.

DATAFILE *load_datafile_callback(const char *filename, void (*callback)


(DATAFILE *d));
Carga el datafile en memoria, llamando a la función de enganche (hook) especificada una
vez por cada objeto en el fichero, pasándole un puntero al objeto leído recientemente.

Relacionado con: find_datafile_object, register_datafile_object, load_datafile,


unload_datafile, load_datafile_object, set_color_conversion, fixup_datafile,
packfile_password.

void unload_datafile(DATAFILE *dat);


Libera todos los objetos de un fichero de datos.

Relacionado con: load_datafile.

DATAFILE *load_datafile_object(const char *filename, const char *objectname);


Carga un objeto específico 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 compresión
general. Mire grabber.txt para más información.

Relacionado con: register_datafile_object, unload_datafile_object, load_datafile,


set_color_conversion.

void unload_datafile_object(DATAFILE *dat);


Libera un objeto previamente cargado con load_datafile_object().

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

Relacionado con: load_datafile, load_datafile_object.

char *get_datafile_property(DATAFILE *dat, int type);


Retorna la propiedad especifica de un objeto, o una cadena vacía si la propiedad no esta
presente. Mire grabber.txt para mas información.

void register_datafile_object(int id, void *(*load)(PACKFILE *f, long size), void


(*destroy)(void *data));
Usado para añadir tipos de objetos propios, especificando las funciones de carga y
destrucción de este tipo. Mire grabber.txt para mas información.

Relacionado con: load_datafile, load_datafile_object.


void fixup_datafile(DATAFILE *data);
Si está usando ficheros de datos compilados (producidos por la utilidad dat2s) que
contienen imágenes truecolor, tiene que llamar esta función una vez haya puesto el modo
de vídeo 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 tamaño 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).

Relacionado con: set_gfx_mode, set_color_conversion.

Usando ficheros de datos


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; - tamaño 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 animación 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 también 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 enseñarlo con el siguiente fragmento
de código:
#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 conversión de
puntero. Ejemplo:
draw_sprite(screen, (BITMAP *)data[LA_IMAGEN].dat, x, y);
Cuando carge un sólo 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 matemáticas de punto fijo


• fixacos
• fixadd
• fixasin
• fixatan
• fixatan2
• fixceil
• fixcos
• fixdiv
• fixfloor
• fixhypot
• fixmul
• fixsin
• fixsqrt
• fixsub
• fixtan
• fixtof
• fixtoi
• ftofix
• itofix

Allegro trae algunas rutinas para trabajar con números 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 fracción, dando un rango de valores de -32768 a 32767 y un
detalle de unos 4 o 5 decimales. Los números de punto fijo pueden ser asignados,
comparados, añadidos, substraídos, negados y desplazados (para multiplicar o dividir por
potencias de 2) usando los operadores de enteros normales, pero tendría que tener cuidado
de usar las rutinas de conversión apropiadas cuando combine números de punto fijo con
enteros o números 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.

Relacionado con: fixtoi, ftofix, fixtof.

int fixtoi(fixed x);


Convierte un valor de punto fijo a entero, redondeando.

Relacionado con: itofix, ftofix, fixtof, fixfloor, fixceil.

int fixfloor(fixed x);


Devuelve el mayor entero menor que x. Esto es, redondea hacia el infinito negativo.

Relacionado con: fixtoi, fixceil.

int fixceil(fixed x);


Devuelve el menor intero mayor que x. Esto es, redondea hacia el infinito positivo.

Relacionado con: fixtoi, fixfloor.

fixed ftofix(float x);


Convierte un valor de coma flotante a punto fijo.

Relacionado con: fixtof, itofix, fixtoi.

float fixtof(fixed x);


Convierte un valor de punto fijo a coma flotante.

Relacionado con: ftofix, itofix, fixtoi.

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
función.

Si hay desbordamiento o división por cero, errno será activado y el valor máximo posible
será devuelto, pero errno no es limpiado si la operación es realizada con éxito. Esto
significa que si va a comprobar un desbordamiento de división, debería poner errno=0 antes
de llamar a fixmul().

Relacionado con: fixadd, fixsub, fixdiv.


fixed fixdiv(fixed x, fixed y);
División de valores de punto fijo: mire fixmul().

Relacionado con: fixadd, fixsub, fixmul.

fixed fixadd(fixed x, fixed y);


A pesar de que los números de punto fijo pueden ser añadidos con el operador normal de
enteros '+', eso no le da protección contra desbordamientos. Si el desbordamiento es un
problema, debería usar esta función. Es mas lenta que los operadores de enteros, pero si hay
un desbordamiento de división, ajustará el tamaño del resultado en vez de dejarlo al azar, y
activara errno.

Relacionado con: fixsub, fixmul, fixdiv.

fixed fixsub(fixed x, fixed y);


Resta de números en punto fijo: mire fixadd().

Relacionado con: fixadd, fixmul, fixdiv.

Trigonometría de punto fijo


Las funciones de raíz cuadrada, seno, coseno, tangente, cosecante y secante están
implementadas usando tablas precalculadas, que son muy rápidas pero no muy exactas. Por
ahora, la cotangente realiza una búsqueda iterativa en la tabla de la tangente, por lo que es
mas lenta que las otras.

Los ángulos están representados en formato binario con 256 siendo igual al círculo
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 círculo completo,
eliminando esos tests cansinos 'if (angle >= 360)'.

fixed fixsin(fixed x);


Mira la tabla precalculada del seno.

Relacionado con: Trigonometría de punto fijo.

fixed fixcos(fixed x);


Mira la tabla precalculada del coseno.

Relacionado con: Trigonometría de punto fijo.


fixed fixtan(fixed x);
Mira la tabla precalculada de la tangente.

Relacionado con: Trigonometría de punto fijo.

fixed fixasin(fixed x);


Mira la tabla de la cosecante.

Relacionado con: Trigonometría de punto fijo.

fixed fixacos(fixed x);


Mira la tabla de la secante.

Relacionado con: Trigonometría de punto fijo.

fixed fixatan(fixed x);


Cotangente de punto fijo.

Relacionado con: Trigonometría de punto fijo.

fixed fixatan2(fixed y, fixed x);


Versión de punto fijo de la rutina atan2() de libc.

Relacionado con: Trigonometría de punto fijo.

fixed fixsqrt(fixed x);


Raíz cuadrada de punto fijo.

Relacionado con: Trigonometría de punto fijo.

fixed fixhypot(fixed x, fixed y);


Hypotenusa en punto fijo (devuelve la raíz cuadrada de x*x + y*y).

Relacionado con: Trigonometría de punto fijo.

Clase de punto fijo


Si está programando en C++ puede ignorar todo lo de arriba y usar la clase "fija", que
sobrecarga muchos operadores para proveer conversión automática desde y hacia valores
enteros y de coma flotante, y llama las rutinas de arriba cuando se necesitan. Sin embargo
no debería 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 erróneo. Debería usar sqrt(x) o x.swrt() en vez de eso.

Alias de punto fijo


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 debería afectar a la mayoría del código existente dado
que existen alias de compatibilidad hacia atrás. Estos alias son funciones estáticas 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 incluír allegro.h.

30 Rutinas matemáticas 3D
• apply_matrix
• apply_matrix_f
• cross_product
• cross_product_f
• dot_product
• dot_product_f
• get_align_matrix
• get_align_matrix_f
• get_camera_matrix
• get_camera_matrix_f
• get_rotation_matrix
• get_rotation_matrix_f
• get_scaling_matrix
• get_scaling_matrix_f
• get_transformation_matrix
• get_transformation_matrix_f
• get_translation_matrix
• get_translation_matrix_f
• get_vector_rotation_matrix
• get_vector_rotation_matrix_f
• get_x_rotate_matrix
• get_x_rotate_matrix_f
• get_y_rotate_matrix
• get_y_rotate_matrix_f
• get_z_rotate_matrix
• get_z_rotate_matrix_f
• identity_matrix
• identity_matrix_f
• matrix_mul
• matrix_mul_f
• normalize_vector
• normalize_vector_f
• persp_project
• persp_project_f
• polygon_z_normal
• polygon_z_normal_f
• qscale_matrix
• qscale_matrix_f
• qtranslate_matrix
• qtranslate_matrix_f
• set_projection_viewport
• vector_length
• vector_length_f

Allegro también contiene algunas funciones de ayuda de 3d para manipular vectores,


construir o usar matrices de transformación, y hacer proyecciones de perspectiva de un
espacio 3d en la pantalla. Estas funciones no son, y nunca serán, una librería 3d total (mi
objetivo es dar rutinas de soporte genéricas, y no código gráfico muy especializado :-) pero
estas funciones pueden serle útiles para desarrollar su propio código 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
corazón apuntará en la dirección positiva del eje z. Esto también significa que para las
rotaciones, si hace que el dedo gordo de su mano derecha siga el eje de rotación, sus dedos
se curvarán en la dirección positiva de la rotación.

Hay dos versiones de todas las funciones matemáticas de 3d: una usando aritmética de
punto fijo, y la otra usando coma flotante. La sintaxis para ambas es idéntica, pero las
funciones y estructuras de coma flotante tienen el sufijo '_f'. Ejemplo: la función
cross_product() de punto fijo tiene el equivalente de coma flotante en cross_product_f(). Si
está programando en C++, Allegro también sobrecarga estas funciones para que las use con
la clase "fija".

La transformación 3d se realiza modelando una matriz. Esta es un array de 4x4 números


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 translación,
rotación 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 después de la otra. Por ejemplo, si tiene una matriz que rota un punto, y otra
que lo mueve en una dirección, puede combinarlas para producir una matriz que realizara la
rotación y translación 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 rotación 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 dimensión, al añadir una coordenada extra: w=1. Esto es algo malo en términos
de eficiencia, pero afortunadamente, es posible realizar una optimización. 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 patrón de qué partes hacen qué. La rejilla 3x3 de arriba a la izquierda
implementa la rotación y el escalado. Los tres valores de arriba de la cuarta columna (d, h y
l) implementan la translación, y siempre y cuando la matriz sea usada sólo para
transformaciones afines, m, n y o serán siempre cero y p siempre será 1. Si no sabe que
significa 'afín', lea a Foley & Van Damme: básicamente cubre el escalado, la translación y
rotación del objeto pero no la proyección. Ya que Allegro usa una función aparte para la
proyección, las funciones de matriz sólo tienen que servir para la transformación afín, 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 manipulación de matrices.

Las matrices se almacenan en estructuras:

typedef struct MATRIX - matriz de punto fijo


{
fixed v[3][3]; - componente 3x3 de escalado y
rotación
fixed t[3]; - componente x/y/z de
translación
} MATRIX;

typedef struct MATRIX_f - matriz de coma flotante


{
float v[3][3]; - componente 3x3 de escalado y
rotación
float t[3]; - componente x/y/z de
translación
} MATRIX_f
extern MATRIX identity_matrix;
extern MATRIX_f identity_matrix_f;
Variable global que contiene la matriz con identidad 'vacía'. Multiplicar por la matriz de
identidad no tiene ningún 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 translación, guardándola 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.
Relacionado con: apply_matrix, get_transformation_matrix, qtranslate_matrix.

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, almacenándola 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
empequeñece las cosas.

Relacionado con: apply_matrix, get_transformation_matrix, qscale_matrix.

void get_x_rotate_matrix(MATRIX *m, fixed r);


void get_x_rotate_matrix_f(MATRIX_f *m, float r);
Construye las matrices de rotación del eje X, almacenándolas en m. Cuando se aplican a un
punto, estas matrices lo rotarán sobre el eje X el ángulo especificado (en binario, 256
grados hacen un círculo).

Relacionado con: apply_matrix, get_rotation_matrix, get_y_rotate_matrix,


get_z_rotate_matrix.

void get_y_rotate_matrix(MATRIX *m, fixed r);


void get_y_rotate_matrix_f(MATRIX_f *m, float r);
Construye las matrices de rotación del eje Y, almacenándolas en m. Cuando se aplican a un
punto, estas matrices lo rotarán sobre el eje Y el ángulo especificado (en binario, 256
grados hacen un círculo).

Relacionado con: apply_matrix, get_rotation_matrix, get_x_rotate_matrix,


get_z_rotate_matrix.

void get_z_rotate_matrix(MATRIX *m, fixed r);


void get_z_rotate_matrix_f(MATRIX_f *m, float r);
Construye las matrices de rotación del eje Z, almacenándolas en m. Cuando se aplican a un
punto, estas matrices lo rotarán sobre el eje Z el ángulo especificado (en binario, 256
grados hacen un círculo).

Relacionado con: apply_matrix, get_rotation_matrix, get_x_rotate_matrix,


get_y_rotate_matrix.

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 transformación que rotará puntos en todos los ejes los grados
especificados. (en binario, 256 grados hacen un círculo).

Relacionado con: apply_matrix, get_transformation_matrix,


get_vector_rotation_matrix, get_align_matrix, get_x_rotate_matrix,
get_y_rotate_matrix, get_z_rotate_matrix.
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 devolverán la matriz
de identidad.

Relacionado con: apply_matrix, get_camera_matrix.

void get_align_matrix_f(MATRIX *m, float xfront, yfront, zfront, float xup, yup,
zup);
Versión en coma flotante de get_align_matrix().

Relacionado con: 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 transformación que rotará puntos sobre todos los vectores x,y,z un
ángulo especificado (en binario, 256 grados hacen un círculo).

Relacionado con: apply_matrix, get_rotation_matrix, get_align_matrix.

void get_transformation_matrix(MATRIX *m, fixed scale, fixed xrot, yrot, zrot, x, y,


z);
Construye una matriz de transformación que rotará puntos en todos los ejes los ángulos
especificados (en binario, 256 grados hacen un círculo), escalará el resultado (pasa el valor
1 si no quiere cambiar la escala), y entonces los trasladará a la posición x, y, z requerida.

Relacionado con: apply_matrix, get_rotation_matrix, get_scaling_matrix,


get_translation_matrix.

void get_transformation_matrix_f(MATRIX_f *m, float scale, float xrot, yrot, zrot, x,


y, z);
Versión en coma flotante de get_transformation_matrix().

Relacionado con: 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 cámara para trasladar objetos del espacio a una vista normalizada
del espacio, preparada para la proyección de perspectiva. Los parámetros x, y, z especifican
la posición de la cámara, xfront, yfront y zfront son los vectores 'de frente' que especifican
hacia adonde apunta la cámara (estos pueden ser de cualquier tamaño, no es necesaria la
normalización), y xup, yup y zup son los vectores de la dirección 'arriba'. El parámetro fov
especifica el campo de visión (el ancho del foco de la cámara) en binario, haciendo 256
grados un círculo. Para proyecciones típicas, un campo de visión de entre 32 a 48 trabajara
bien. Finalmente, la razón de aspecto es usada para el escalado en la dimensión Y
relativamente al eje X, para que pueda ajustar las proporciones de la imagen final (ponga a
uno para no escalar).

Relacionado con: apply_matrix, get_align_matrix.

void get_camera_matrix_f(MATRIX_f *m, float x, y, z, xfront, yfront,zfront, float


xup, yup, zup, fov, aspect);
Versión en coma flotante de get_camera_matrix().

Relacionado con: 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 añade el 'offset'
de translación, por lo que no hay que crear dos matrices temporales y multiplicarlas.

Relacionado con: get_translation_matrix.

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 añade el factor de
escalación, por lo que no hay que crear dos matrices temporales y multiplicarlas.

Relacionado con: get_scaling_matrix.

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 mátrices de entrada, pero es más rápido cuando las entradas y la salida son todas
distintas). La matriz resultante tendrá el mismo efecto que la combinación de m1 y m2, p.ej
cuando son aplicadas en un punto, (p * out) = ((p * m1) * m2). Cualquier número de
transformaciones se puede concatenar de esta forma. Fíjese que la multiplicación de
matrices no es communtaiva, así matrix_mul(m1,m2) != matrix_mul(m2,m1).

Relacionado con: apply_matrix.

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 Pitágoras.

Relacionado con: normalize_vector.


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
dirección que el vector original, pero tiene una longitud de uno.

Relacionado con: vector_length, dot_product, cross_product.

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.

Relacionado con: cross_product, normalize_vector.

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 polígonos.

Relacionado con: dot_product, polygon_z_normal, normalize_vector.

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 vértices especificados (que
deben ser parte de un polígono convexo). Esto es usado principalmente en la ocultación 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 polígonos
de una escena. Si la normal es negativa, el polígono se puede eliminar, si es cero, el
polígono está perpendicular a la pantalla.

Relacionado con: cross_product.

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 transformación de la matriz m, almacenando el resultado
en el punto (*xout, *yout, *zout).

Relacionado con: matrix_mul.

void set_projection_viewport(int x, int y, int w, int h);


Ajusta el punto de visión usado para escalar la salida de la función persp_project(). Pase las
dimensiones de la pantalla y el área donde la quiere dibujar, que típicamente será 0, 0,
SCREEN_W, SCREEN_H.

Relacionado con: persp_project.


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 parámetros anteriormente ajustados por
set_projection_viewport(). Esta función proyecta desde la pirámide de vista normalizada,
que tiene una cámara 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
cámara tiene un ángulo de visión de 90 grados, es decir, los planos x=z y -x=z serán los
bordes izquierdo y derecho de la pantalla, y los planos y=z y -y=z serán la parte superior e
inferior de la pantalla. Si quiere un campo de visión diferente a la posición de la cámara,
debería transformar todos sus objetos con la matriz de visión apropiada. Ejemplo, para
obtener el efecto de haber girado la cámara 10 grados a la izquierda, rote todos sus objetos
10 grados a la derecha.

Relacionado con: set_projection_viewport.

31 Rutinas matemáticas para usar


cuaterniones
• apply_quat
• get_rotation_quat
• get_vector_rotation_quat
• get_x_rotate_quat
• get_y_rotate_quat
• get_z_rotate_quat
• identity_quat
• matrix_to_quat
• quat_interpolate
• quat_mul
• quat_slerp
• quat_to_matrix

Los cuaterniones son una forma alternativa de representar la parte de rotación de una
transformación, y pueden ser más fáciles de manipular que las matrices. Como con una
matriz, usted puede codificar transformaciones geométricas en una, concatenar varias de
ellas para mezclar múltiples transformaciones, y aplicarlas a un vector, pero sólo pueden
almacenar rotaciones puras. La gran ventaja es que puede interpolar precisamente entre dos
cuaterniones para obtener una rotación parcial, evitando los enormes problemas de la
interpolación más convencional con ángulos eulerianos.

Los cuaterniones sólo poseen versiones de punto flotante, sin ningún sufijo "_f". Por otro
lado, la mayoría de las funciones de cueterniones se corresponden con una función
matricial que realiza una operación similar.
Cuaternión 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 números, pero eso está más
allá del alcance de esta documentación. Los cuaterniones funcionan -- créame.

extern QUAT identity_quat;


Variable global que contiene el cuaternión identidad 'que no hace nada'. Multiplicar por el
cuaternión 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 rotación, almacenándolos en q. Cuando sean aplicados a
un punto, éstos cuaterniones lo rotarán sobre el eje relevante el ángulo especificado (dado
en binario, 256 grados forman un círculo).

void get_rotation_quat(QUAT *q, float x, float y, float z);


Construye un cuaternión que rotará puntos alrededor de los tres ejes las cantidades
especificadas (dadas en binario, 256 grados forman un círculo).

void get_vector_rotation_quat(QUAT *q, float x, y, z, float a);


Construye un cuaternión que rotará puntos alrededor del vector x,y,z el ángulo especificado
(dado en binario, 256 grados forman un círculo).

void quat_to_matrix(const QUAT *q, MATRIX_f *m);


Construye una matriz de rotación a partir de un cuaternión.

void matrix_to_quat(const MATRIX_f *m, QUAT *q);


Construye un cuaternión a partir de una matriz de rotación. La translación es descartada
durante la conversión. Use get_align_matrix_f() si la matriz no está ortonormalizada,
porque de otra forma podrían pasar cosas extrañas.

void quat_mul(const QUAT *p, const QUAT *q, QUAT *out);


Multiplica dos cuaterniones, almacenando el resultado en out. El cuaternión resultante
tendrá el mismo efecto que la combinación 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 multiplicación del cuaternión 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 cuaternión q, almacenando el resultado en (*xout, *yout,
*zout). Esto es un poquito más lento que apply_matrix_f(), así que úselo para trasladar unos
pocos puntos. Si usted tiene muchos puntos, es mucho más 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 cuaternión que representa una rotación entre from y to. El argumento t puede
ser cualquiera entre 0 y 1, y representa dónde estará el resultado entre from y to. 0 devuelve
from, 1 devuelve to, y 0.5 devolverá una rotación exactamente en la mitad. El resultado es
copiado a out. Esta función creará una rotación 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 más control sobre cómo es hecha la rotación. El
parámetro how puede ser alguno de estos valores:

QUAT_SHORT - como quat_interpolate(), usa el camino


más corto
QUAT_LONG - la rotación será mayor que 180 grados
QUAT_CW - rotación horaria vista desde arriba
QUAT_CCW - rotación antihoraria vista desde arriba
QUAT_USER - los cuaterniones son interpolados
exactamente como
son dados.

32 Rutinas GUI
• active_dialog
• active_menu
• alert
• alert3
• broadcast_dialog_message
• centre_dialog
• d_bitmap_proc
• d_box_proc
• d_button_proc
• d_check_proc
• d_clear_proc
• d_ctext_proc
• d_edit_proc
• d_icon_proc
• d_keyboard_proc
• d_list_proc
• d_menu_proc
• d_radio_proc
• d_rtext_proc
• d_shadow_box_proc
• d_slider_proc
• d_text_list_proc
• d_text_proc
• d_textbox_proc
• d_yield_proc
• dialog_message
• do_dialog
• do_menu
• file_select
• file_select_ex
• find_dialog_focus
• gfx_mode_select
• gfx_mode_select_ex
• gui_bg_color
• gui_button_proc
• gui_ctext_proc
• gui_edit_proc
• gui_fg_color
• gui_font_baseline
• gui_list_proc
• gui_menu_draw_menu
• gui_menu_draw_menu_item
• gui_mg_color
• gui_mouse_b
• gui_mouse_focus
• gui_mouse_x
• gui_mouse_y
• gui_mouse_z
• gui_shadow_box_proc
• gui_strlen
• gui_text_list_proc
• gui_textout
• init_dialog
• object_message
• offer_focus
• popup_dialog
• position_dialog
• set_dialog_color
• shutdown_dialog
• update_dialog

Allegro posee un gestor de diálogos 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 más complicados que cree. Allegro le deja definir sus propios tipos de objetos
y escribir nuevos procesos de diálogo, por lo que tendrá control total sobre los aspectos
visuales de la interfaz mientras todavía usa Allegro para controlar el ratón, teclado,
joystick, etc.

Un diálogo GUI se almacena como un array de objetos DIALOG, de los cuales cada uno
cuenta con los siguientes parámetros:

typedef struct DIALOG


{
int (*proc)(int, DIALOG *, int); - proceso del diálogo
(controlador de
mensajes)
int x, y, w, h; - posición y tamaño
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
específicos del objeto
} DIALOG;
El array debe acabar con un objeto que tiene el proceso de diálogo puesto a NULL.

El campo de bits puede contener cualquier combinación de los siguientes bits:

D_EXIT - este objeto debe cerrar el diálogo al


activarse
D_SELECTED - este objeto está seleccionado
D_GOTFOCUS - este objeto tiene el foco de entrada
D_GOTMOUSE - el ratón 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 múltiplo de dos mayor
que éste esta
libre para que lo use
Cada objeto es controlado por un proceso de diálogo, que se almacena en el puntero proc.
Este será llamado por el gestor de diálogos cuando se produzca alguna acción que involucre
al objeto, o puede llamarlo directamente con la función object_message(). El proceso de
diálogo 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). Fíjese que d es un puntero a un objeto especifico y no al diálogo entero.

El proceso del diálogo debería devolver uno de los siguientes valores:

D_O_K - estado normal de retorno


D_CLOSE - le dice al gestor de diálogos que cierre
el diálogo
D_REDRAW - le dice al gestor de diálogos que
redibuje el diálogo
D_REDRAWME - dice al gestor de diálogos 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 diálogo se pueden llamar con cualquiera de estos mensajes:

MSG_START:
Le dice al objeto que se inicialice. El gestor de diálogo manda esto a todos los objetos del
diálogo justo antes de mostrarlo.

MSG_END:
Se manda a todos los objetos cuando se cierra un diálogo, permitiéndoles que hagan los
procesos de limpieza que necesiten.

MSG_DRAW:
Le dice al objeto que se dibuje en pantalla. El puntero del ratón se desactivara cuando este
mensaje sea mandado, para que el código de dibujado no se preocupe por él.

MSG_CLICK:
Informa al objeto que un botón del ratón a sido pulsado mientras el ratón estaba encima del
objeto. Normalmente el objeto realizará su propio seguimiento del ratón mientras el botón
esté pulsado, y sólo volverá de este controlador de mensaje cuando se suelte el botón.

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 botón 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
algún botón 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 código de carácter igual al de la función readkey() (valor ASCII en el
byte bajo, scancode en el byte alto) como parámetro c. Si el objeto trata con la pulsación de
teclas debería devolver D_USED_CHAR, en caso contrario debería devolver D_O_K para
permitir operar al interfaz de teclado por defecto. Si necesita acceder a la entrada de un
carácer Unicode, debería usar MSG_UCHAR en vez de MSG_CHAR.

MSG_UCHAR:
Si un objeto ignora la entrada MSG_CHAR, este mensaje será mandado inmediatemente
después de él, pasando el valor completo de la tecla en Unicode como parámetro c. Esto le
permite leer códigos de carácteres 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 diálogos buscará un objeto con un atajo de teclado asociado
en el campo key, mandándole un MSG_KEY. Si esto falla, mandará un MSG_XCHAR al
resto de los objetos del diálogo, permitiéndoles responder a pulsaciones de tecla especiales
incluso cuando no tienen el foco de entrada. Normalmente debería 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
diálogo 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 ratón 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 ratón 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 ratón esta encima suyo, es responsable de redibujarse él solo como
respuesta a estos mensajes.

MSG_IDLE:
Es mandado cuando el diálogo 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 número del grupo se pasa en el parámetro del mensaje c.

MSG_WHEEL:
Enviado al objeto que tenga el foco de entrada cada vez que se mueve la rueda del ratón. El
parámetro c de mensaje contiene el número de clicks.

MSG_LPRESS, MSG_MPRESS, MSG_RPRESS:


Enviado cuando el botón correspondiente del ratón es presionado.

MSG_LRELEASE, MSG_MRELEASE, MSG_RRELEASE:


Enviado cuando el botón correspondiente del ratón es soltado.

MSG_USER:
El primer valor de mensaje libre. Cualquier número 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 diálogo estándar. Puede usarlos tal como vienen para crear
una interfaz de objetos simples, o puede usarlos desde sus propios proceses de diálogo,
resultando en una especie de herencia de objetos. Por ejemplo, podría hacer un objeto que
llama d_button_proc para dibujarse, pero controla el mensaje de pulsación del botón del
ratón de forma diferente, o un objeto que llama d_button_proc para cualquier cosa excepto
para dibujarse a si mismo, por lo que se comportaría como un botón normal pero podría ser
completamente diferente.

Desde la versión 3.9.33 (CVS) de Allegro, algunos objetos y menús de la interfaz gráfica de
usuario son dibujados de forma diferente en comparación con versiones anteriores de
Allegro. Los cambios son:

• Las sombras bajo d_shadow_box_proc y d_button_proc son siempre negras.


• El cambio más importante (y visible inmediatamente), es que algunos objetos se
dibujan más pequeños. La diferencia es exáctamente un pixel tanto vertical como
horizontalmente, comparando con versiones anteriores. La razón es que en
versiones anteriores, estos objetos eran demasiado grandes para la pantalla - su
tamaño era d->;w+1 y d->;h+1 en pixels (y no d->;w y d->;h, como debería 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 diálogos antiguos para que visualmente sean iguales al
compilar con la nueva versión de Allegro, simplemente incremente el tamaño 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
pequeña flecha junto al nombre del menú hijo, apuntando a la derecha - para que los
usuarios vean que ese menú tiene submenús - 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
diálogo.

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 carácteres '&' de la cadena serán reemplazados por líneas
debajo del siguiente carácter, para enseñar los atajos de teclado (tal y como en MS
Windows). Para enseñar 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 botón objeto (el campo dp apunta a una cadena de texto). Este objeto puede ser
seleccionado pinchando sobre él con el ratón o presionando su atajo de teclado. Si se pone
el bit D_EXIT, el seleccionarlo provocará el cierre del diálogo. Si no, encenderá y apagará
el diálogo. Como en d_text_proc(), puede usar el caracter '&' para enseñar el atajo de
teclado del botón.

int d_check_proc(int msg, DIALOG *d, int c);


Este es un ejemplo de cómo puede derivar objetos desde otros objetos. La mayoría 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 tamaño que la altura del objeto).

int d_radio_proc(int msg, DIALOG *d, int c);


Un objeto de botón de radio. Un diálogo puede contener cualquier número de grupos de
botones de radio: el seleccionar un botón de radio provoca que los otros botones del mismo
grupo se desactiven. El campo dp apunta a una cadena de texto, d1 requiere el número de
grupo especifico, y d2 es el estilo del botón (0=círculo, 1=cuadrado).

int d_icon_proc(int msg, DIALOG *d, int c);


Un botón bitmap. El color fg es usado por la línea de puntos que enseña el foco, y el color
bg hace la sombra que rellena la parte superior e izquierda del botón cuando este se
presiona. d1 es la "profundidad", es decir, el número 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 línea del foco. dp apunta a un bitmap para el icono,
mientras que dp2 y dp3 son las imágenes de botón 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 código
ASCII en el campo de la tecla del diálogo del objeto (un caracter como 'a' responde a la
pulsación de tecla, un número 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 función apuntada por dp. Esto debería devolver un entero, el cual se
pasará de vuelta al gestor de diálogo, 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 ratón), se puede teclear texto en el
objeto. El campo d1 indica el número máximo de carácteres que se aceptaran, y d2 es la
posición 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 ratón o usando las teclas. Si el bit D_EXIT está activado,
haciendo doble click en la lista de ítems cerrará el diálogo. El índice del objeto
seleccionado se encuentra en el campo d1, y d2 es usado para indicar hasta dónde se ha
desplazado la lista de ítems. El campo dp apunta a una función que será llamada para
obtener información sobre los contenidos de la lista. Esto debería seguir el modelo:

char *foobar(int index, int *list_size);


Si index es cero o positivo, la función debe devolver un puntero a la cadena que debe
enseñarse en la posición index en la lista. Si index es negativo, debe devolver NULL y en
list_size debe poner el número de ítems de la lista.

Para crear una lista de selección múltiple, haga apuntar dp2 a un array de variables de un
byte que indican el estado de selección de cada ítem de la lista (distinto de cero para
entradas seleccionadas). ¡Esta tabla debe ser al menos tan grande como el número 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
carácteres 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 enseñarse 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 carácter. El campo d1 se usa internamente para
guardar el número de líneas de texto, y d2 es usado para guardar hasta dónde 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.
Enseñará una barra de desplazamiento vertical si h es más grande o igual a w, de otro modo
enseñará una barra horizontal. El campo dp puede contener un bitmap opcional que usará la
barra de desplazamiento, y dp2 puede contener una función opcional de callback, que será
llamada cada vez que d2 cambie. La función callback debería seguir el prototipo:

int function(void *dp3, int d2);


El objeto d_slider_proc devolverá el valor de la función callback.

int d_menu_proc(int msg, DIALOG *d, int c);


Este objeto es una barra de menú que abre menús hijos cuando se pincha en él o cuando
alguna combinación alt+tecla es pulsada y se corresponde con algún atajo del menú. El
objeto ignora muchos de los campos de la estructura de diálogo, particularmente el color se
coge de las variables gui_*_color, y el ancho y alto se calculan automáticamente (los
cambos w y h de la estructura DIALOG sólo se usan como tamaño mínimo). El campo dp
apunta a un array de estructuras de menú: mire do_menu() para más información. El nivel
de arriba del menú será visualizado como una barra horizontal, pero cuando aparezcan los
menús hijos, aparecerán con el formato vertical usual usado por do_menu(). Cuando un
ítem del menú es seleccionado, el valor de retorno de la función del menú se pasa al gestor
de diálogo, para que las funciones de sus menús puedan devolver D_O_K, D_REDRAW, o
D_CLOSE.

Relacionado con: Menus gui, active_menu, gui_menu_draw_menu.

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 más que hacer que esperar las acciones del
usuario. Debería poner al menos un objeto de este tipo en cada array ya que podría ser
necesario en sistemas con un algoritmo de planificación de tareas inusual (por ejemplo
QNX) para hacer la interfaz totalmente responsiva al usuario.

El comportamiento del gestor de diálogos se controla con las siguientes variables:

extern int gui_mouse_focus;


Si esta activado, el foco de entrada sigue al puntero del ratón, 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 diálogos estándar (alertas, menús, y el selector
de ficheros). Por defecto son 255 y 0.

Relacionado con: gui_mg_color, set_dialog_color.

extern int gui_mg_color;


El color usado para enseñar los diálogos en gris (los que tienen el bit D_DISABLED
activado). Por defecto es 8.
Relacionado con: gui_fg_color, set_dialog_color.

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 tamaño 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 ratón. 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 posición del ratón, o para leer
datos de una fuente totalmente diferente.

gui font
Puede cambiar el puntero global a 'font' para hacer que los objetos del GUI usen otra cosa
que la fuente estándar 8x8. Los procesos estándar de diálogo, los menús, las cajas de alerta,
trabajarán con fuentes de cualquier tamaño, pero el diálogo gfx_mode_select() aparecerán
mal con cualquier cosa que no sean fuentes de 8x8.

int gui_textout(BITMAP *bmp, const char *s, int x, y, color, centre);


Función de ayuda usada por las rutinas GUI. Dibuja una cadena de texto en la pantalla,
interpretando el caracter '&' como el subrayado para enseñar los atajos de teclado.
Devuelve el ancho de la cadena en pixels.

Relacionado con: gui_strlen.

int gui_strlen(const char *s);


Función de ayuda usada por las rutinas GUI. Devuelve la longitud de una cadena de texto
en pixels, ignorando los carácteres '&'.

Relacionado con: gui_textout.

void position_dialog(DIALOG *dialog, int x, int y);


Mueve un array de objetos de diálogo a la posición de pantalla especificada (indicando la
esquina superior izquierda del diálogo).

Relacionado con: centre_dialog.


void centre_dialog(DIALOG *dialog);
Mueve un array de diálogos de objetos para que estén centrados en la pantalla.

Relacionado con: set_dialog_color.

void set_dialog_color(DIALOG *dialog, int fg, int bg);


Pone el color de primer plano y fondo de un array de diálogo de objetos.

Relacionado con: gui_fg_color, gui_mg_color, centre_dialog.

int find_dialog_focus(DIALOG *dialog);


Busca el diálogo 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 enseño el
diálogo la ultima vez, por lo que pueda llamar a do_dialog(dlg, find_dialog_focus(dlg));

Relacionado con: do_dialog, init_dialog, offer_focus.

int offer_focus(DIALOG *d, int obj, int *focus_obj, int force);


Ofrece el foco de entrada a un objeto particular. Normalmente esta función envía 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 función que el
objeto debe tener el foco de entrada.

Relacionado con: find_dialog_focus.

int object_message(DIALOG *dialog, int msg, int c);


Envía un mensaje a un objeto y devuelve la respuesta generada. Recuerde que el primer
parámetro es el objeto del diálogo (no el array completo) al que desea enviar el mensaje.
Por ejemplo, para hacer que el segundo objeto del diálogo se dibuje, podría escribir:
object_message(&dialog[1], MSG_DRAW, 0);

Relacionado con: dialog_message.

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 diálogo
devuelve otro valor que no sea D_O_K, la función devuelve el valor y hace apuntar a obj al
índice del objeto que produjo ese mensaje.

Relacionado con: object_message, broadcast_dialog_message.

int broadcast_dialog_message(int msg, int c);


Manda un mensaje a todos los objetos del diálogo activo. Si cualquiera de los procesos de
diálogo devuelve otros valores que no sean D_O_K, devuelve ese valor.
Relacionado con: dialog_message, active_dialog.

int do_dialog(DIALOG *dialog, int focus_obj);


La función básica del gestor de diálogo. Esta enseña el diálogo (un array de objetos de
diálogo, acabados por uno con el proceso de diálogo puesto a NULL), y pone el foco de
entrada a focus_obj (-1 si no quiere que nada tenga el foco de entrada). La función
interpreta la entrada del usuario y despacha mensajes a medida que se requiera, hasta que
uno de los procesos de diálogo le dice que lo cierre. Entonces devuelve el índice del objeto
que causó el cierre.

Relacionado con: find_dialog_focus, popup_dialog, init_dialog, centre_dialog,


set_dialog_color.

int popup_dialog(DIALOG *dialog, int focus_obj);


Como do_dialog(), pero almacena los datos de la pantalla antes de dibujar el diálogo y los
recupera cuando el diálogo es cerrado. El área de pantalla a guardar es calculada según las
dimensiones del primero objeto en el diálogo, por lo que el resto de los objetos deben estar
dentro de él.

Relacionado con: do_dialog.

DIALOG_PLAYER *init_dialog(DIALOG *dialog, int focus_obj);


Esta función da acceso de bajo nivel a la misma funcionalidad que do_dialog(), pero le
permite combinar la caja de diálogo con sus propias estructuras de objeto. Inicializa un
diálogo, devolviendo un puntero al objeto reproductor que puede ser usado con
update_dialog() y shutdown_dialog(). Con estas funciones, puede implementar su propia
versión de do_dialog() con las líneas:
DIALOG_PLAYER *player = init_dialog(dialog, focus_obj);

while (update_dialog(player))
;

return shutdown_dialog(player);

Relacionado con: update_dialog, shutdown_dialog, do_dialog.

int update_dialog(DIALOG_PLAYER *player);


Actualiza el estado de un diálogo de objeto devuelto por init_dialog(). Devuelve TRUE si
el diálogo sigue activo, o FALSE si se ha cerrado. Si devuelve FALSE, depende de usted
llamar a shutdown_dialog() o continuar con la ejecución. El objeto que requirió la salida
puede ser determinado desde el campo player->;obj.

Relacionado con: init_dialog.


int shutdown_dialog(DIALOG_PLAYER *player);
Destruye el player de diálogo de objeto devuelto por init_dialog(), devolviendo el objeto
que causó la salida (esto es lo mismo que el valor de do_dialog()).

Relacionado con: init_dialog.

extern DIALOG *active_dialog;


Puntero global al diálogo activado más recientemente. Esto puede ser útil si un objeto
necesita recorrer la lista de diálogos "hermanos".

Relacionado con: do_dialog, init_dialog, broadcast_dialog_message.

Menus gui
Los menús 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 tamaño cero para visualizar el ítem
como una barra divisoria no seleccionable. Si la cadena contiene un caracter de tabulación
"\t", el texto que sigue será justificado a la derecha, por ejemplo para enseñar información
sobre el atajo del teclado. El puntero proc es una función que será llamada cuando el ítem
del menú sea seleccionado, y child apunta a otro menú, permitiéndole hacer menús
anidados. proc y child pueden ser ambos NULL. La función proc devuelve un entero que es
ignorado si el menú fue llamado por do_menu(), pero que es devuelto al gestor de diálogo
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 enseñar un símbolo de marcado si se activa el bit D_SELECTED.
Con la alineación y fuente por defecto, la marca sobreescribiría el texto del menú, por lo
que si va a usar ítems de menú con símbolo 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 símbolo de marcado.
Relacionado con: do_menu, d_menu_proc, gui_menu_draw_menu.

int do_menu(MENU *menu, int x, int y)


Enseña y anima el menú emergente en la pantalla en las coordenadas especificadas (estas
serán 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. Fíjese que el valor de retorno no
puede indicar una selección de menús hijo, por lo que tendrá que usar funciones "callback"
si quiere menús multi-nivel.

Relacionado con: Menus gui, d_menu_proc, active_menu,


gui_menu_draw_menu.

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 dónde fue llamada.

Relacionado con: Menus gui.

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 serán llamadas cuando un menú necesite ser dibujado, por lo
que puede cambiar el aspecto de los menús.

A gui_menu_draw_menu() se le pasará la posición y tamaño del menú. Debería 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. También debería ser dibujado en la pantalla (screen).

Relacionado con: Menus gui.

int alert(const char *s1, *s2, *s3, const char *b1, *b2, int c1, c2);
Enseña una caja de alerta emergente, conteniendo tres líneas 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 botón 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 botón (esto es consistente con la típica alerta "Ok",
"Cancelar").

Relacionado con: alert3, gui_fg_color.


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.

Relacionado con: alert, gui_fg_color.

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.

Relacionado con: file_select_ex, gui_fg_color.

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 título. El
parámetro 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
selección del usuario se devuelve alterando el buffer path, cuya longitud máxima en bytes
está indicada por el parámetro size. Recuerde que debería tener como mínimo espacio para
80 carácteres (no bytes), por lo que debería 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
carácteres de atributos. Cualquier atributo escrito solo, o con un '+' antes de él, indica que
sólo 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
sólo 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 sólo
lectura pero no los directorios. El diálogo del selector de ficheros será reescalado a la
anchura y altura especificadas y al tamaño de la fuente. Si alguno de los parámetros está a
cero, entonces la función escalará el diálogo a la dimensión apropiada de la pantalla.
Devuelve cero si fue cerrada con el botón Cancelar, y distinto de cero si se cerró con OK.

Relacionado con: gui_fg_color.

int gfx_mode_select(int *card, int *w, int *h);


Enseña el diálogo de selección de modo gráfico de Allegro, que permite al usuario
seleccionar el modo y tarjeta de vídeo. Almacena la selección en las tres variables, y
devuelve cero si se cerró con el botón Cancelar y distinto de cero si se cerró con OK.

Relacionado con: gfx_mode_select_ex, set_gfx_mode, gui_fg_color.


int gfx_mode_select_ex(int *card, int *w, int *h, int *color_depth);
Versión extendida del diálogo de selección de modo gráfico, que permite al usuario
seleccionar tanto el número de colores como la resolución y el controlador de vídeo. Esta
versión de la función lee los valores iniciales de los parámetros cuando se activa, por lo que
puede especificar los valores por defecto.

Relacionado con: gfx_mode_select, set_color_depth, set_gfx_mode, gui_fg_color.

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 serán usadas por los
diálogos estándar 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.

Relacionado con: alert, alert3, file_select, gfx_mode_select, gui_fg_color.

33 Detalles específicos del DOS


• DIGI_*/DOS
• GFX_*/DOS
• i_love_bill
• JOY_TYPE_*/DOS
• MIDI_*/DOS
• split_modex_screen

Drivers: JOY_TYPE_*/DOS
La biblioteca para DOS soporta los siguientes tipos de parámetros para la función
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 sólo puede elegir el controlador
de joystick estándar, Sidewider, GamePad Pro, o GrIP, pero usará información del
fichero de configuración si éste existe (el fichero puede ser creado usando la
utilidad setup o llamando a la función save_joystick_data()), por lo que siempre
puede usar JOY_TYPE_AUTODETECT en su código y elegir el tipo de hardware
exacto desde el programa setup.
• JOY_TYPE_NONE
Controlador vacío para máquinas 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 analógico, y un sombrero de 4 direcciones.
• JOY_TYPE_WINGEX
Un Logitech Wingman Extreme, que debería funcionar con cualquier joystick
compatible Thrustmaster Mk.I. Tiene soporte para cuatro botones y un sombrero.
Esto también funciona con el Wingman Warrior, si conecta el conector de 15 pins
(¡recuerde desconectar el conector de 9 pins!) y si ajusta el pequeño interruptor de
adelante a la posición "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 dirección).
• JOY_TYPE_SIDEWINDER_AG
Versión 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 dirección).
• JOY_TYPE_GRIP
Controlador GrIP de Gravis, usando el fichero de controlador grip.gll.
• JOY_TYPE_GRIP4
Versión del controlador GrIP de Gravis que está restringido a moverse sólamente 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 información sobre el
cable paralelo necesario. El controlador automágicamente detecta qué tipos de pads
PSX están conectados de entre los digitales, analógicos (modo rojo o verde),
NegCon, multi taps, pistolas de luz Namco, Jogcons (volantes con retroalimentación
de fuerza), y el ratón. Si el mando no es reconocido es tratado como un mando
analógico, queriendo decir que el controlador debería funcionar con casi cualquier
cosa. Puede conectar los mandos como desee, pero sólo serán usados los primeros 8.
El Dual Shock de Sony o el Jogcon de Namco se volverán a colocar ellos mismos
en modo digital después de no haber sido muestreados durante 5 segundos. Esto es
normal, pasa lo mismo en una Playstation, están diseñados para detener cualquier
vibración en caso de que la máquina anfitrión se cuelgue. Otros mandos
multifunción tendrán rarezas similares. Sin embargo, si esto le ocurre a un mando
Jogcon, el botón 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 vídeo de mi tarjeta funciona bien con ésto (una
Hercules Stingray 128/3D 8Mb). Los modos de vídeo TV también deberían
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 información sobre el adaptador
hardware necesario. Soporta hasta cuatro mandos en un único puerto paralelo. No es
necesario caliblar el control analógico, 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 podría tener con este
controlador es que es físicamente imposible poner el stick analógico 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 analógico. 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 ejecución
de mi maquina con ambos controladores, pero no hay modo de evitarlo. En una
(muy) tosca suposición diría 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 código fuente (src/dos/multijoy.c) información
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 más detalles sobre cómo 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 companía IO-
DATA (éstas existen en variantes PCI, PCI2 e ISA).

Relacionado con: install_joystick.

Drivers: GFX_*/DOS
La librería para DOS soporta los siguientes parámetros de tarjeta para la función
set_gfx_mode():

• GFX_TEXT
Volver al modo texto.
• GFX_AUTODETECT
Deja que Allegro escoja un driver gráfico apropiado.
• GFX_AUTODETECT_FULLSCREEN
Autodetecta el driver gráfico, pero sólo usará drivers a pantalla completa, fallando si
no están disponibles en la plataforma actual.
• GFX_AUTODETECT_WINDOWED
Igual que el anterior, pero sólo con drivers en ventana. Esto siempre fallará bajo
DOS.
• GFX_SAFE
Controlador especial para cuando quiere establecer un modo gráfico seguro y no le
importa realmente en qué resolución o profundidad de color. Mire para más detalles
la documentación de set_gfx_mode().
• GFX_VGA
El modo 13h estándar 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 también
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.
o Resoluciones estables del modo-X:
 Razón de aspecto cuadrado: 320x240
 Razón de aspecto oblicuo: 256x224, 256x240, 320x200, 320x400,
320x480, 320x600, 360x200, 360x240, 360x360, 360x400, 360x480

Estos han funcionado en cada tarjeta/monitor que he probado.

o Resoluciones de modo-X inestables:


 Razón de aspecto cuadrado: 360x270, 376x282, 400x300
 Razón de aspecto oblicuo: 256x200, 256x256, 320x350, 360x600,
376x308, 376x564, 400x150, 400x600

Estos sólo funcionan en algunos monitores. Funcionaron bien en mi vieja


máquina, pero no se llevan bien con mi nuevo monitor. Si está preocupado
por la posibilidad de dañar su monitor usando estos modos, no lo esté. Por
supuesto no estoy dando ninguna garantía al respecto, y si su hardware
explota es una pena, pero no creo que este tipo de ajustes puedan hacer daño
alguno. De la documentación del programa TWEAK de Robert Schmidt:
"Hace tiempo, poner valores o combinaciones ilegales o no soportadas en
los registros de la tarjeta de vídeo podía 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 oído que usar
TWEAK o cambiar manualmente los registros de la VGA hayan ocasionado
daño alguno."

• La mayoría de las funciones de dibujo en el modo-X son más lentas que en el modo
13h, debido a la complejidad de la organización planar del bitmap, pero los rellenos
de áreas sólidas y los blits alineados al plano de una parte de la memoria de vídeo a
otra pueden ser significativamente más rápidos, 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 páginas 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
función request_refresh_rate(). Los modos VESA estándares son 640x480,
800x600, y 1024x768. Estos deberían 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
mayoría de las tarjetas soportan resoluciones de 15 y 16 bits, pero si es posible se
recomendaría implementar ambas (no es tan difícil...) en caso de que una no esté
disponible. Algunas tarjetas permiten color verdadero de 24 y 32 bits, en cuyo caso
la elección es entre 24 (salvar memoria) o 32 (va más rápido), 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 también soportan 640x400, 1280,1024 y
1600x1200, pero estos modos no siempre están 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 resolución 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,
permitiéndle hacer scroll o intercambio de páginas sin la complejidad del modo-X,
pero desafortunadamente no son un estándar, por lo que necesitará el Display
Doctor para poder usarlos.
• GFX_VBEAF
VBE/AF es un superconjunto del estándar VBE 2.0, que trae un API para acceder a
características de aceleración por hardware. Los controladores VBE/AF actualmente
sólo están 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 discusión detallada sobre la
aceleración por hardware, lea la documentación 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
erróneo puede bloquear su máquina cuando estos controladores estén en uso. Esto
significa que puede ser buena idea usar VESA mientras depura su programa, y
activar VBE/AF sólo cuando el código 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, sólo funcionará en tarjetas que soporten una resolución 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 conmutación
de bancos, aunque el scroll por hardware y el intercambio de páginas no serán
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 explícitamente a set_gfx_mode().

Relacionado con: 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 (autodetección)
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

Relacionado con: detect_digi_driver, install_sound, install_sound_input.

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
(autodetección)
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)

Relacionado con: detect_midi_driver, install_sound, install_sound_input.

void split_modex_screen(int line);


Esta función sólo está disponible en modo-X. Permite la división de la pantalla VGA en dos
partes por una línea especifica. En la mitad superior de la pantalla puede hacer scroll a
cualquier punto de la memoria de video mediante la función scroll_screen(), pero la parte
inferior será siempre fija y mostrará el contenido de la posición (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 más baja de la memoria de video y después creará
dos sub-bitmaps para acceder a ambas secciones (en examples/exscroll.c tiene una
demostración de cómo se puede hacer esto). Para desactivar la división, llame a
split_modex_screen(0).

Relacionado con: set_gfx_mode, scroll_screen.

extern int i_love_bill;


Cuando se ejecuta en entorno DOS puro, el temporizador reprograma dinámicamente 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 mayoría de sistemas multitarea (sobre todo bajo Windows), por lo
tanto, existe un modo alternativo que bloquea la interrupción 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 más
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 además se activa el modo de temporizador
de razón fija.

Relacionado con: install_timer, allegro_init, os_type.

34 Detalles específicos de Windows


• blit_from_hdc
• blit_to_hdc
• convert_bitmap_to_hbitmap
• convert_hbitmap_to_bitmap
• convert_hpalette_to_palette
• convert_palette_to_hpalette
• DIGI_*/Windows
• draw_to_hdc
• GFX_*/Windows
• MIDI_*/Windows
• set_gdi_color_format
• set_palette_to_hdc
• stretch_blit_from_hdc
• stretch_blit_to_hdc
• win_get_dc
• win_get_window
• win_release_dc
• win_set_window
• win_set_wnd_create_proc

Un programa para Windows que use Allegro sólo tiene que incluír uno o más ficheros del
árbol include/allegro, o allegro.h; no obstante, si también necesita llamar directamente a
funciones no portables del API Win32, deberá incluír el fichero de cabecera específico 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 símbolo de preprocesador
ALLEGRO_AND_MFC antes de incluír cualquier fichero de cabecera de Allegro para que
afxwin.h sea incluído. Tenga en cuenta que en este último caso, las macros de depuración
ASSERT() y TRACE() serán 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 estándar main(). Allegro está configurado para crear aplicaciones GUI
por defecto y hacer unos trucos de magia para que la función regular main() funcione sin
problemas, pero para esto necesita que escriba END_OF_MAIN() justo tras su función
main(). Si no quiere hacer esto, puede incluír winalleg.h y escribir una función 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 función
WinMain() y que los trucos de magia sean desactivados definiendo el símbolo de
preprocesador ALLEGRO_NO_MAGIC_MAIN antes de incluír los ficheros de cabecera
de Allegro.

Si quiere crear una aplicación de consola con Allegro, debe definir el símbolo de
preprocesador USE_CONSOLE antes de incluir los ficheros de cabecera de Allegro; esto
indicará a la librería que use características del modo consola y que desactive el procesado
especial de la función 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á automáticamente
como icono de aplicación. En caso contrario, Allegro usará el icono por defecto
IDI_APPLICATION.

DirectX requiere que los bitmaps de vídeo y sistema estén bloqueados en memoria (locked)
antes de que pueda dibujar en ellos. Esto se hará automáticamente, pero podrá conseguir
habitualmente una ejecucíon más óptima haciéndolo usted mismo: mire la función
acquire_bitmap() para más detalles.

Debido a un gran descuido en el diseño de DirectX, no hay manera de preservar los


contenidos de la memoria de vídeo 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 vídeo, puede ser destruido en cualquier
momento. Puede usar la función set_display_switch_callback() para arreglárselas 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 parámetros de tarjeta para la función
set_gfx_mode():

• GFX_TEXT
Esto cierra el modo gráfico abierto previamente con set_gfx_mode.
• GFX_AUTODETECT
Deja que Allegro escoja un controlador gráfico apropiado.
• GFX_AUTODETECT_FULLSCREEN
Autodetecta el driver gráfico, pero sólo usará drivers a pantalla completa, fallando si
no están disponibles en la plataforma actual.
• GFX_AUTODETECT_WINDOWED
Igual que el anterior, pero sólo con drivers en ventana. Esto siempre fallará bajo
DOS.
• GFX_SAFE
Controlador especial para cuando quiere establecer un modo gráfico seguro y no le
importa realmente en qué resolución o profundidad de color. Mire para más detalles
la documentación de set_gfx_mode().
• GFX_DIRECTX
Igual que GFX_DIRECTX_ACCEL.
• GFX_DIRECTX_ACCEL
El controlador normal DirectX a pantalla completa, corriendo con aceleración por
hardware.
• GFX_DIRECTX_SOFT
Controlador a pantalla completa DirectX que sólo usa dibujado por software,
ignorando las características de aceleración por hardware.
• GFX_DIRECTX_SAFE
Controlador a pantalla completa DirectX simplificado que no soporta ninguna
aceleración por hardware, bitmaps de vídeo o sistema, etc.
• GFX_DIRECTX_WIN
El driver en ventana de DirectX, usando conversión de color cuando la profindidad
de color no sea igual a la del escritorio de Windows. La conversión de color es
mucho más lenta que dibujar directamente y no está soportada en escritorios con
una profundidad de color de 15 o 16 bits por pixel. Esta última limitación existe
para resolver la limitación de desktop_color_depth() (lea más 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 características 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
limitación de desktop_color_depth() (lea más 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 emulación hardware del
cursor del ratón para acelerar las operaciones básicas de éste (como operaciones
GUI).

Relacionado con: set_gfx_mode.

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

Relacionado con: detect_digi_driver, install_sound, install_sound_input.


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 específica de la plataforma para integrar
Allegro sin problemas con cualquier programa Win32 de propósito general. Para usar estas
rutinas, debe incluir winalleg.h tras otros ficheros de cabecera de Allegro.

Relacionado con: detect_midi_driver, install_sound, install_sound_input.

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 ningún modo gráfico, 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 función debe ser llamada
*antes* de iniciar la librería con allegro_init() o instalando el driver de sistema con
autodetección (SYSTEM_AUTODETECT). Le permite enganchar Allegro a una ventana
ya existente y evita que la librería crée la suya, dejándole el control total de la ventana; en
particular, usted será responsable de manejar los eventos como siempre (Allegro
monitorizará automáticamente algunos de ellos, pero no los filtrará). Puede usar cualquier
componente de la librería (ratón, teclado, sonido, temporización, etc) excepto el subsistema
gráfico.

void win_set_wnd_create_proc(HWND (*proc)(WNDPROC));


Hace que Allegro use una función definida por el usuario para crear su ventana. Esta
función debe ser llamada *antes* de iniciar la librería con allegro_init() o instalando el
driver de sistema con autodetección (SYSTEM_AUTODETECT). Le permite personalizar
la ventana de Allegro pero sólo en su creación: 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 función 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 librería sin restricciones de la forma habitual.
HDC win_get_dc(BITMAP *bmp);
Recupera el handle del dispositivo de contexto del vídeo 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().

Rutinas GDI
Estas rutinas GDI son algo muy específico 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 estáticos (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 dinámicos (por ejemplo elementos que reaccionan según 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 además 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 conversión usan la paleta actual como una tabla de
conversión 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 explícitamente, (por ejemplo, por otra aplicación) ¡la paleta actual de Allegro
no es actualizada con ello!

Para usar estas rutinas debe incluir winalleg.h tras los demás ficheros de cabecera de
Allegro.

void set_gdi_color_format(void);
Le dice a Allegro que use el mapa de colores del GDI para imágenes de color verdadero.
Esto es opcional, pero hará que las conversiones funcionen más rápido. Si usted va a llamar
a ésta función, debería hacerlo después de iniciar Allegro y ántes de crear gráficos.
void set_palette_to_hdc(HDC dc, PALETTE pal);
Selecciona y realiza una paleta de Allegro sobre el contexto de dispositivo específico.

HPALETTE convert_palette_to_hpalette(PALETTE pal);


Convierte una paleta de Allegro a una paleta de Windows y devuelve su manejador. Usted
debería llamar a DeleteObject() cuando no la necesite más.

Relacionado con: convert_hpalette_to_palette.

void convert_hpalette_to_palette(HPALETTE hpal, PALETTE pal);


Convierte una paleta de Windows en una paleta de Allegro.

Relacionado con: convert_palette_to_hpalette.

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 debería llamar DeleteObject() cuando no necesite más este mapa de bits.

Relacionado con: convert_hbitmap_to_bitmap.

BITMAP *convert_hbitmap_to_bitmap(HBITMAP bitmap);


Crea un bitmap de Allegro en memoria desde un DDB de Windows.

Relacionado con: convert_bitmap_to_hbitmap.

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 parámetros que la función draw_sprite().

Relacionado con: blit_to_hdc, stretch_blit_to_hdc, 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 parámetros que la función blit().

Relacionado con: draw_to_hdc, stretch_blit_to_hdc, blit_from_hdc, 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 parámetros que la función stretch_blit().
Relacionado con: draw_to_hdc, blit_to_hdc, stretch_blit_from_hdc, 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 parámetros que la función blit(). Vea stretch_blit_from_hdc() para más
detalles.

Relacionado con: stretch_blit_from_hdc, blit_to_hdc, blit.

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 parámetros que la función stretch_blit(). Usa la paleta actual de Allegro
y realiza una conversión a ésta paleta, sin importar la paleta DC actual. Así que si usted está
realizando un blit desde el modo de 8 bits, debería primero actualizar la paleta DC con la
función set_palette_to_hdc().

Relacionado con: blit_from_hdc, stretch_blit_to_hdc, stretch_blit.

35 Detalles específicos de Unix


• DIGI_*/Unix
• GFX_*/Linux
• GFX_*/X
• MIDI_*/Unix

Para poder localizar cosas como los ficheros de configuración o traducción, Allegro
necesita conocer el path de su ejecutable. Ya que no hay forma estándar para hacer eso,
necesita capturar una copia de sus parámetros 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 función main(). Muy
fácil, realmente, y si se olvida de hacerlo, obtendrá un agradable error de enlazado sobre
una función inexistente _mangled_main que se lo recordará :-)

Drivers: GFX_*/Linux
Cuando use Linux en modo consola, Allegro soporta los siguientes parámetros de tarjeta
para la función set_gfx_mode():

• GFX_TEXT
Vuelve al modo texto.
• GFX_AUTODETECT
Permite que Allegro elija un controlador gráfico apropiado.
• GFX_AUTODETECT_FULLSCREEN
Autodetecta el driver gráfico, pero sólo usará drivers a pantalla completa, fallando si
no están disponibles en la plataforma actual.
• GFX_AUTODETECT_WINDOWED
Igual que el anterior, pero sólo con drivers en ventana. Esto siempre fallará bajo
DOS.
• GFX_SAFE
Controlador especial para cuando quiere establecer un modo gráfico seguro y no le
importa realmente en qué resolución o profundidad de color. Mire para más detalles
la documentación de set_gfx_mode().
• GFX_FBCON
Usa el dispositivo framebuffer (ej: dev/fb0). Esto requiere que tenga soporte para
framebuffer compilado en su núcleo, 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 versión 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 aceleración de gráficos por hardware.
• GFX_SVGALIB
Usa la librería SVGAlib para mostrar gráficos. Esto requiere permisos de
superusuario si su versión de SVGAlib los requiere.
• GFX_VGA
GFX_MODEX
Usa acceso directo al hardware para ajustar resoluciones VGA estándar o modo-X,
soportando los mismos modos que las versiones DOS de estos controladores.
Requiere permisos de superusuario.

Relacionado con: set_gfx_mode, GFX_*/X.

Drivers: GFX_*/X
Cuando esté bajo X, Allegro soporta los siguientes parámetros de tarjeta para la función
set_gfx_mode():

• GFX_TEXT
Esto cierra el modo gráfico abierto previamente con set_gfx_mode.
• GFX_AUTODETECT
Permite que Allegro elija un controlador gráfico apropiado.
• GFX_AUTODETECT_FULLSCREEN
Autodetecta el driver gráfico, pero sólo usará drivers a pantalla completa, fallando si
no están disponibles en la plataforma actual.
• GFX_AUTODETECT_WINDOWED
Igual que el anterior, pero sólo con drivers en ventana. Esto siempre fallará bajo
DOS.
• GFX_SAFE
Controlador especial para cuando quiere establecer un modo gráfico seguro y no le
importa realmente en qué resolución o profundidad de color. Mire para más detalles
la documentación de set_gfx_mode().
• GFX_XWINDOWS
El controlador gráfico X estándar. Esto debería 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 extensión XF86VidMode para ejecutarse a pantalla completa incluso
sin permisos de superusuario. Seguirá usando el protocolo X estándar, así que
espere obtener el mismo bajo rendimiento que con el driver en ventana.
• GFX_XDGA
Usa la extensión DGA 1.0 de XFree86 para escribir directamente en la superficie de
vídeo. DGA es normalmente más rápido que el modo X estándar, 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 además cambia la resolución de la pantalla para que se
ejecute en pantalla completa. Este controlador requiere permisos de superususario.
• GFX_XDGA2
Usa la nueva extensión DGA 2.0 de XFree86 4.0.x. Esta funcionará en pantalla
completa, y soportará aceleración por hardware si está disponible. El controlador
requiere premisos de superusuario.
• GFX_XDGA2_SOFT
Igual que GFX_XDGA2, pero desactiva la aceleración por hardware. Este
controlador requiere permisos de superusuario.

Relacionado con: set_gfx_mode, GFX_*/Linux.

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

Relacionado con: detect_digi_driver, install_sound, install_sound_input.

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

Relacionado con: detect_midi_driver, install_sound, install_sound_input.

36 Detalles específicos de BeOS


• DIGI_*/BeOS
• GFX_*/BeOS
• MIDI_*/BeOS

Drivers: GFX_*/BeOS
Allegro para BeOS soporta los siguientes parámetros para la función set_gfx_mode():

• GFX_TEXT
Esto cierra el modo gráfico abierto previamente con set_gfx_mode.
• GFX_AUTODETECT
Permite que Allegro elija un controlador gráfico apropiado.
• GFX_AUTODETECT_FULLSCREEN
Autodetecta el driver gráfico, pero sólo usará drivers a pantalla completa, fallando si
no están disponibles en la plataforma actual.
• GFX_AUTODETECT_WINDOWED
Igual que el anterior, pero sólo con drivers en ventana. Esto siempre fallará bajo
DOS.
• GFX_SAFE
Controlador especial para cuando quiere establecer un modo gráfico seguro y no le
importa realmente en qué resolución o profundidad de color. Mire para más detalles
la documentación de set_gfx_mode().
• GFX_BEOS_FULLSCREEN
Pantalla completa en modo exclusivo. Soporta resoluciones iguales o mayores que
640x480, y usa aceleración por hardware si está disponible.
• GFX_BEOS_FULLSCREEN_SAFE
Igual que GFX_FULLSCREEN, pero desactiva la aceleración.
• GFX_BEOS_WINDOWED
Modo rápido en ventana usando la clase BDirectWindow. No todas las tarjetas
gráficas soportan esto.

Relacionado con: set_gfx_mode.


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

Relacionado con: detect_digi_driver, install_sound, install_sound_input.

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

Relacionado con: detect_midi_driver, install_sound, install_sound_input.

37 Detalles específicos de QNX


• DIGI_*/QNX
• GFX_*/QNX
• MIDI_*/QNX
• qnx_get_window

Drivers: GFX_*/QNX
Allegro para QNX soporta los siguientes parámetros card para la función set_gfx_mode():

• GFX_TEXT
Esto cierra el modo gráfico abierto previamente con set_gfx_mode.
• GFX_AUTODETECT
Permite que Allegro elija un controlador gráfico apropiado.
• GFX_AUTODETECT_FULLSCREEN
Autodetecta el driver gráfico, pero sólo usará drivers a pantalla completa, fallando si
no están disponibles en la plataforma actual.
• GFX_AUTODETECT_WINDOWED
Igual que el anterior, pero sólo con drivers en ventana.
• GFX_SAFE
Controlador especial para cuando quiere establecer un modo gráfico seguro y no le
importa realmente en qué resolución o profundidad de color. Mire para más detalles
la documentación de set_gfx_mode().
• GFX_PHOTON_DIRECT
Modo exclusivo a pantalla completa a través de Photon.
• GFX_PHOTON
Modo ventana en una ventana Photon.

Relacionado con: set_gfx_mode.

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

Relacionado con: detect_digi_driver, install_sound, install_sound_input.

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 específica de la plataforma para integrar
Allegro con programas QNX de propósito general. Para usar estas rutinas, debe incluir
qnxalleg.h tras los otros ficheros de cabecera de Allegro.

Relacionado con: detect_midi_driver, install_sound, install_sound_input.

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 ningún
modo gráfico, a no ser que haya
instalado el driver de sistema neutral
(SYSTEM_NONE). 38 Diferencias entre
plataformas
Aquí tiene un rápido resumen de las cosas que pueden causar problemas cuando mueva su
código de una plataforma a otra (puede encontrar una versión detallada de esto en la
sección docs de la página web de Allegro).

Las versiones Windows y Unix requieren que escriba END_OF_MAIN() tras su función
main(), lo que transforma mágicamente su main() de estilo ANSI C en un WinMain() de
estilo Windows, y permite que el código Unix obtenga una copia de sus parámetros argv[].

En muchas plataformas Allegro funcionará lentamente si espera que bloquee


automáticamente los bitmaps cuando dibuje sobre ellos. Para mejorar el rendimiento,
necesita llamar usted mismo acquire_bitmap() y release_bitmap(), e intentar minimizar el
número de bloqueos.

La versión Windows puede perder el contenido de la memoria de vídeo 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,
debería llamar poll_mouse() y poll_keyboard() en los lugares apropiados.

Allegro define un número estándar 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 serán 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 múltiples sub-bitmaps de
vídeo (ej: DOS), en vez de cada bitmap sea una entidad totalmente única (ej. Windows).

ALLEGRO_CONSOLE_OK
Definido cuando no está en modo gráfico, y hay una consola en modo texto a la cual puede
mandar mensajes con printf(), salida estándar que puede ser capturada y redirigida por el
usuario incluso cuando está en modo gráfico. Si este define está ausente, está ejecutando su
programa en un entorno como Windows, el cual no tiene salida estándar.

ALLEGRO_LFN
Distinto de cero si hay soporte para ficheros de nombres largos, o cero si está limitado al
formato 8.3 (en la versión DJGPP esto es una variable dependiente del entorno durante la
ejecución).

INLINE
Use esto en lugar de la palabra reservada modificadora de función "inline" y su código
funcionará correctamente en cualquiera de los compiladores soportados.

ZERO_SIZE
Use esto para declarar arrays de tamaño 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 código
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 carácter 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 carácter.

DEVICE_SEPARATOR
Definido al carácter que separa el nombre de fichero del dispositivo (dos puntos para DOS
y Windows), o cero si no hay dispositivos explícitos en las rutas (ej: Unix).

USE_CONSOLE
Si define esto antes de incluir los ficheros de cabecera de Allegro, la versión Windows hará
que su programa se compile como una aplicación de consola en vez del programa normal
en modo gráfico.

END_OF_MAIN()
Al poner esto tras su función 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 tamaño de su ejecutable


Hay gente que se queja de que Allegro produce ejecutables muy grandes. Esto es cierto:
con la versión DJGPP, un simple programa "hola mundo" ocupará unas 200k, aunque este
tamaño por ejecutable es mucho menor en plataformas que soportan enlazado dinámico.
Pero no se preocupe, Allegro ocupa un tamaño 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 relación entre código de biblioteca y programa debería ponerse manos a la obra y
escribir más código de programa para equilibrar la cosa :-)

Dicho esto, hay varias cosas que puede hacer para reducir el tamaño 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 compresión de
alrededor de un 40%. Cuando use DJGPP: para empezar, lea la sección 8.14 del
FAQ de DJGPP, y tome nota del parámetro -s. ¡Y no se olvide de compilar su
programa con las optimizaciones activadas!
• Si un programa DOS va a ser usado en un número limitado de resoluciones, puede
especificar los controladores gráficos que desea incluir con su código:
• 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 construcción debe ser incluida sólo en uno de sus ficheros C. El orden de los
nombres es importante, porque la rutina de auto detección 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 líneas 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


excepción de los modos de 15 y 16 bits: éstos comparten una buena porción de
código, así que si está incluyendo uno, no hay razón 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 código:
• 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 música 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 sólo quiere incluir
controladores de sonido digital, simplemente escriba
DECLARE_MIDI_DRIVER_LIST() para no incluir controladores de música.

• 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 estándar incluye soporte para joysticks duales, número superior de


botones, Flightstick Pro, y Wingman Extreme, porque éstos son variaciones
menores del código básico.

• Si _realmente_ está decidido a reducir los tamaños, mire el comienzo del fichero
include/allegro/alconfig.h y verá las líneas:
• #define ALLEGRO_COLOR8
• #define ALLEGRO_COLOR16
• #define ALLEGRO_COLOR24
• #define ALLEGRO_COLOR32
Si comenta cualquiera de estas definiciones y reconstruye la librería, tendrá una
versión sin soporte para las profundidades de color ausentes, lo que incluso reducirá
más 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 código.

Nota: los métodos mencionados para quitar drivers gráficos no usados sólo es aplicable a
las versiones de la biblioteca enlazadas estáticamente, ejemplo: DOS. En plataformas
Windows y Unix, puede crear Allegro como una DLL o biblioteca compartida, lo cual evita
que se puedan usar estos métodos, 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
reducción de tamaño dramática mezclando el código del programa setup con su programa
principal, para que sólo sea necesario enlazar una copia de Allegro. Lea setup.txt para más
detalles. En la versión DJGPP, tras comprimir su ejecutable, esto le ahorrará unos 200k en
comparación con tener dos programas separados para setup y el propio juego.

40 Depurando
• al_assert
• al_trace
• ASSERT
• register_assert_handler
• register_trace_handler
• TRACE

Hay tres versiones de la biblioteca Allegro: el código normal optimizado, con soporte extra
para depurar, y una versión para medir el rendimiento. Lea los ficheros readme específicos
de cada plataforma para saber cómo instalar y enlazar con estas versiones alternativas. A
pesar de que obviamente querrá usar la versión optimizada para la versión final de su
programa, puede ser muy útil enlazar con la versión de depuración, porque hará la tarea de
depuración más fácil, y porque incluye aserciones que le ayudarán a encontrar errores en su
código con antelación. Allegro contiene varias funciones para ayudar en la depuración:

void al_assert(char *file, int line);


Genera una aserción en el fichero en la línea especificada. El parámetro 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 ejecución del programa con un mensaje de error. Normalmente
usará la macro ASSERT() en vez de llamar directamente a esta función.
Relacionado con: ASSERT, al_trace, register_assert_handler.

void al_trace(char *msg, ...);


Muestra un mensaje de depuración usando una cadena con formato printf() codificada en
ASCII. Si ha instalado una función 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 función.

Relacionado con: TRACE, al_assert, register_trace_handler.

void ASSERT(condition);
Macro ayudante de depuración. Normalmente se convierte en nada, pero si ha definido
DEBUGMODE antes de incluir los ficheros de cabecera de Allegro, comprobará la
condición indicada y llamará a al_assert() si ésta falla.

Relacionado con: al_assert, TRACE, register_assert_handler.

void TRACE(char *msg, ...);


register_trace_handler Macro ayudante de depuración. 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().

Relacionado con: al_trace, ASSERT.

void register_assert_handler(int
(*handler)(char *msg)); register_trace_handler Permite usar una función propia para tratar
las aserciones fallidas. A su función 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 gráfico sin abortar el programa.

Relacionado con: al_assert, ASSERT.

void register_trace_handler(int
(*handler)(char *msg)); register_assert_handler Permite usar una función propia para tratar
los mensajes de trazado. A su función 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.

Relacionado con: al_trace, TRACE.

41 Comandos makefile
Hay un número de opciones que puede usar para controlar exactamente cómo compilar
Allegro. En plataformas Unix esto se hace pasando argumentos al script de configuración
(ejecute "configure --help" para obtener una lista), en otras plataformas puede ajustar las
siguientes variables de entorno:

• DEBUGMODE=1
Genera una versión para depurar, en vez de la versión normal optimizada.
• PROFILEMODE=1
Genera una versión para medir rendimientos, en vez de la versión normal
optimizada.
• WARNMODE=1
Selecciona avisos de compilador más estrictos. Si está planeando trabajar en
Allegro, en vez de simplemente usarlo, debería asegurarse de tener este modo
activado.
• STATICLINK=1 (sólo MSVC y Mingw32)
Enlazar de forma estática, en vez de usar la DLL por defecto.
• TARGET_ARCH_COMPAT=[cpu] (implementado en la mayoría de plataformas
GNU)
Esta opción optimizará el código 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 mayoría de plataformas
GNU)
Esta opción optimizará el código para el procesador indicado. Tome nota de que el
código generado *NO* funcionará en procesadores anteriores. Ejemplo: set
TARGET_ARCH_EXCL=i586
• TARGET_OPTS=[opts] (implementado en la mayoría de plataformas GNU)
Esta opción le permite personalizar optimizaciones generales del compilador.
• CROSSCOMPILE=1 (sólo djgpp)
Le permite compilar la versión djgpp de la biblioteca bajo Linux, usando djgpp
como compilador cruzado.
• ALLEGRO_USE_C=1 (sólo djgpp)
Permite generar la biblioteca con djgpp usando el código C de dibujado en vez de
las rutinas en ensamblador. Esto sólo es útil para hacer pruebas, ya que la versión
con ensamblador es más rápida.

Si usted sólo desea recompilar un programa test específico o una utilidad, puede
especificarlo como parámetro del make, ej: "make demo" o "make grabber". El makefile
tiene además varios comandos especiales:

• 'default'
El proceso normal. Compila la versión 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
documentación.
• '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
documentación.
• 'lib'
Compila la versión actual de la biblioteca (ya sea optimizada, para depurar o medir
el rendimiento, seleccionada por las variables de entorno anteriores).
• 'install'
Copia la versión 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 documentación de las fuentes ._tx.
• 'docs-dvi' (sólo 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' (sólo 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' (sólo Unix)
Esto genera páginas de manual de Unix para cada función o variable de Allegro, y
las instala. El segundo comando comprime las páginas antes de instalarlas.
• 'install-info' o 'install-gzipped-info' (sólo Unix)
Convierte la documentación 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
recompilación total la próxima vez que ejecute make. Este comando está diseñado
de tal forma que si ejecuta "make install" y luego "make clean", todavía tendrá una
versión funcional de Allegro . Esto requiere la utilidad rm de estilo Unix instalada,
por ejemplo del paquete GNU fileutils.
• 'distclean'
Como 'make clean', pero más todavía. Elimina todos los archivos ejecutables y la
documentación en formato HTML, dejándole con exactamente los mismos archivos
que hay cuando descomprime una distribución nueva de Allegro.
• 'veryclean'
¡Use esto con extrema precaución! Esta orden borra absolutamente todo archivo
generado, incluyendo algunos que puede ser difícil recrear. Después de ejecutar este
comando, una simple recompilación no funcionará: al menos tendrá que ejecutar
"make depend", y tal vez también fixdll.bat si está usando la biblioteca de
Windows. Este objetivo hace uso de herramientas no estándar como SED, así que a
no ser que sepa usted lo que está haciendo y tenga estas herramientas instaladas, no
debería usarlo.
• 'depend'
Regenera los archivos de dependencias (obj/*/makefile.dep). Es necesario ejecutar
esto tras "make veryclean", o cuando se le añadan nuevas cabeceras a los fuentes de
Allegro.
• 'compress' (sólo 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.

Cambios de la 4.0.0 a la 4.0.1 (Marzo 2002)


• Muchos cambios menores, muchas clarificaciones en la documentación.
• Peter Wang corrigió la instalación de librerías compartidas bajo FreeBSD.
• Peter Wang y Eric Botcazou corrigieron los problemas de autodetección de VGA y
SVGAlib.
• Eric Botcazou corrigió un problema bajo X11 cuando se usaba la extensión MIT X-
SHM.
• Eric Botcazou corrigió un interbloqueo durante la salida cuando se usaba una
ventana de usuario junto con los temporizadores de Windows.
• Eric Botcazou desactivó los backbuffers inservibles para el driver seguro de
DirectX.
• Peter Wang hizo que el driver de sonido Alsa use un modo no bloqueante durante la
detección de ALSA PCM.
• Sven Sandberg añadió soporte de enteros long long a usprintf() y otras funciones.
• Robert J. Ohannessian corrigió el blender diferencial.
• Peter Wang corrigió una condición de carrera cuando se cerraba el modo gráfico
bajo X.
• Elias Pschernig hizo que todos los diálogos activos se redibujen tras un cambio de
aplicación.
• Peter Wang hizo que fbcon sea un driver con prioridad, para que pueda aparecer
antes que VGA.
• Javier Gonzalez corrigió un fallo en el código de entrada DirectSound.
• Eric Botcazou corrigió el SIGSEV de salida cuando se usaba la combinación de
teclas de salida de emergencia bajo QNX.
• Eric Botcazou corrigió el problema de llamadas C-a-ensamblador para los
programas compilados con Borland C++.
• Eric Botcazou limpió el caótico (y algo incorrecto) código de gestión de bitmaps de
DirectDraw.
• Sven Sandberg mejoró el algoritmo de subdivisión de bitmaps de vídeo.
• Sven Sandberg corrigió los problemas de los makefiles en Windows (especialmente
para Borland) cuando se compila Allegro bajo Win98.
• Peter Wang quitó el parche que activaba los alias de funciones de punto fijo bajo
IRIX.
• Vincent Penquerc'h corrigió un problema con el temporizador SIGALRM y
SWITCH_PAUSE.
• Javier Gonzalez corrigió un problema de latencia con los flujos de audio.
• Laurence Withers hizo que el exportador de fuentes use la paleta actual durante la
generación de la salida.
• Elias Pschernig realizó algunos cambios al grabber: añadió un gancho de salida;
monitoriza si algo fue modificado; cuando sale del grabber y el fichero fue
modificado, la ventana popup ahora tiene una tercera opción para salir y salvar; el
título de la ventana muestra el nombre del fichero actual, y si éste ha sido
modificado; corrigió las exportaciones de fuentes multicolor.
• Sven Sandberg optimizó de nuevo la función create_light_table().
• Attila Szilagyi corrigió el scroll horizontal con SVGAlib.
• Eric Botcazou corrigió problemas de sincronización bajo QNX.
• Grzegorz Adam Hankiewicz hizo que la tabla de contenidos del comienzo de cada
sección de la documentación esté ordenada alfabéticamente.
• Eric Botcazou corrigió la actualización de la pantalla tras un retorno del modo
ahorro de energía en los drivers Windows de ventana y overlay.
• Richard Reeve corrigió un fallo estúpido con la detección gcc 3.0.x.
• Angelo Mottola corrigió la compilación estática de keyconf bajo BeOS debido al
driver de teclado pckeys.
• Eric Botcazou corrigió el fallo no-devolver-el-foco-tras-salir bajo Windows.
• Michael Bukin corrigió un fallo en la versión C de textprintf en bitmaps de 24 bpp,
tras ser descubierto por Bertrand Coconnier.
• Eric Botcazou corrigió un fallo en la rutina de conversión de color MMX de 32 a 15
bpp.
• Eric Botcazou corrigió un problema de enlazado de DLL bajo Borland C++ Builder
4.
• Sven Sandberg hizo que exaccel responda mejor al usuario.
• Sven Sandberg corrigió un problema de nombres cortos bajo DOS.

Cambios de la 3.9.40 a la 4.0.0 (Diciembre


2001)
• Muchos cambios menores.
• Eric Botcazou modularizó los drivers VGA/Modo-X bajo Linux.
• Peter Wang corrigió el fallo que provocaba un segfault en Modo-X bajo Linux con
threads.
• Peter Wang hizo que X11 use la señal SIGTERM en vez de exit() cuando se usa la
combinación de tres teclas ctrl+alt+fin. Esto soluciona el problema de cuelgues de
sonido cuando se cerraban algunos programas.
• Eric Botcazou añadió soporte de os_version y os_revision al port QNX y añadió una
sección específica sobre QNX a la documentación.
• Peter Wang añadió una zona muerta para las lecturas digitales de los ejes del
joystick bajo Linux, tal y como sugirió Goerge Foot e hizo que el driver mirase
en /dev/input/js# antes que /dev/js#.
• Peter Wang renombró las funciones de punto fijo para que usen el prefijo "fix" en
vez de "f", para evitar conflictos de nombres con algunas libc. La compatibilidad
hacia atrás se provee mediante funciones estáticas inline.
• Peter Wang solucionó dos problemas con salidas de emergencia bajo Linux/Unix.
• Eric Botcazou cambió la lógica de actualización del driver gráfico Photon para
QNX.
• Eric Botcazou añadió documentación sobre la utilidad wfixicon, con la ayuda de
Laurence Withers.
• Angelo Mottola hizo que allegro_message bajo BeOS sea unicode y escribió un
nuevo driver de teclado para BeOS (usando el sistema de pckeys compartidas).
• Eric Botcazou corrigió un problema con el parche de David Capello que
robaba/devolvía el foco del ratón.
• Peter Wang hizo que pasar NULL a install_allegro() como el parámetro atexti_ptr
signifique que allegro_exit() no será instalada como rutina atexit(), tal y como
sugirió Javier Gonzalez.
• Lorenzo Petrone añadió la utilidad gfxinfo.
• Eric Botcazou añadió soporte fetch_mode_list() al driver Photon Direct bajo QNX.
• Peter Wang hizo que desktop_color_depth() se capaz de devolver 15 bpp bajo X.
• Grzegorz Adam Hankiewicz actualizó las cadenas de textos traducidas al español.
• Peter Wang corrigió un problema con la secuencia de cierre de X.
• Eric Botcazou arregló el proceso de compilación bajo QNX, reorganizó el formato
del código fuente del port QNX y arregó otras cosas.
• Peter Wang desactivó el código SVGAlib que listaba los modos gráficos dado que
estaba causando problemas con otros drivers.
• Angelo Mottola añadió notas sobre BeOS al documento de compatibilidad ABI.
• Eric Botcazou corrigió un fallo en el código de bloqueo de Windows que provocaba
cuelgues del grabber en eventos de cambio de aplicación.
• Eric Botcazou corrigió un fallo en el manejo de sub-bitmaps recursivos bajo
Windows.
• Eric Botcazou corrigió un fallo que evitaba cargar packfiles antiguos que usaban
password de protección en el grabber.
• Lorenzo Petrone añadió dos respuestas al FAQ sobre problemas con DGA2.
• Grzegorz Adam Hankiewicz reorganizó la estructura del directorio docs.
• Stepan Roh actualizó la traducción al cheqo.
• Javier Gonzalez corrigió un fallo con el driver DirectSound relacionado con modos
de reproducción con bucles.
• David Capello corrigió un problema con los submenús que se superponían a sus
padres, donde el foco volvería al menú padre en vez de al hijo.
Cambios de la 3.11 a la 3.9.40 (Noviembre
2001)
• 3.9.40: Eric Botcazou activó el soporte SSE bajo Linux. También redujo el retardo
del código de inicio del Sidewinder bajo DOS. Hizo que los defines _ALL_DLL de
MinGW32 sean consistentes con otras plataformas.
• 3.9.40: Henrik Stokseth mejoró el make install para que sólo instale los ficheros de
cabecera necesarios de include/allegro/plataforma.
• 3.9.40: Vincent Penquerc`h actualizó 7 ficheros makefiles tras separar las cabeceras.
• 3.9.40: Robert J. Ohannessian añadió dos nuevos puntos de entrada a la estructura
GFX_VTABLE.
• 3.9.40: Eric Botcazou sustituyó los sprintf() por snprintf() en el código Linux/Unix.
Incrementó el retraso del código de cambio de tarea de Windows. Corrigió el
selector de modo gráfico he hizo que use unicode. Añadió el programa de
verificación filetest. Corrigió más problemas de cadenas unicode. Unificó el manejo
de variables de directorios de sistema en los ficheros makefile de Windows. Hizo
dos cadenas del selector gráfico traducibles.
• 3.9.40: Ben Davis añdió soporte para temporizadores con parámetros bajo
Windows.
• 3.9.40: Eric Botcazou corrigió el fallo de las rutinas ensamblador cuando eran
usadas con sub-bitmaps. Corrigió un problema de la nueva organización de ficheros
de cabecera para plataformas que no tienen soporte de ensamblador.
• 3.9.40: George Foot y Eric Botcazou corrigieron las funciones en C fceil() y
ffloor().
• 3.9.40: Chris Graham sugirió añadir un nuevo bit para ficheros comprimidos en
Windows NTFS.
• 3.9.40: Henrik Schmidt y Eric Botcazou encontraron una solución alternativa al
problema de cambio de tarea bajo Windows.
• 3.9.40: Eric Botcazou rehizo el proceso de compilación para Borland C++. Ahora
funciona para BC++ 5.5. Hizo de pack_fdopen() una función interna exportada.
Cambió el código de flujos de audio de 16 bits de DirectSound a la versión 3.9.38.
• 3.9.40: Vincent Penquerc'h contribuyó una gran reorganización/separación de los
ficheros de cabecera de Allegro. Henrik y Eric hicieron algunas tareas de limpieza y
corrección relacionadas.
• 3.9.40: Peter Wang actualizó la documentación de put_backslash.
• 3.9.40: Eric Botcazou modificó la forma en que las superficies DirectDraw son
enumeradas. Corrigió errores/avisos de compilación con BC++. Hizo de
generate_optimized_palette_ex() una función estática. Solucionó las limitaciones de
al_findfirst() y for_each_file() para DOS. Movió código dependiente de plataforma
fuera de src/fsel.c.
• 3.9.40: Peter Wang actualizó la documentación de temporizadores para plataformas
no DOS. Añadió un documento de compatibilidad ABI.
• 3.9.40: Javier Gonzalez eliminó todas las referencias a la compilación con RSXNT.
• 3.9.40: Vincent Penquerc'h hizo que los usuarios puedan proveer su propia rutina
ustrdup().
• 3.9.40: Robin Burrows corrigió dos problemas con el código DirectDraw.
• 3.9.40: Peter Wang corrigió el problema donde XUnlockDisplay era llamado tras
XCloseDisplay.
• 3.9.40: Eric Botcazou eliminó el antiguo controlador Sidewinder en ensamlador.
Hizo limpieza de uso de buffers en DIGMID. Corrigió el soporte unicode del driver
DIGMID. Cambió todas las ocurrencias de SEND_MESSAGE() por
object_message().
• 3.9.40: Annie Testes descubrió un desorden en la secuencia de cierre bajo X.
• 3.9.40: Eric Botcazou incrementó el tamaño de los buffers de nombres de ficheros a
1024 bytes.
• 3.9.40: Sven Sandberg mejoró el script fix.bat.
• 3.9.40: David Capello corrigió un problema con los clicks del ratón perdidos en la
GUI.
• 3.9.40: Vincent Penquerc'h eliminó dos tamaños fijos de lista codificados a cañón
en el grabber.
• 3.9.40: Peter Wang añadió una pequeña clarificación sobre mouse_accel_factor.
• 3.9.40: Eric Botcazou hizo que las funciones de depuración usen cadenas ASCII.
Añadió algunos defines para tener compatibilidad hacia atrás con las anteriores
banderas cpu_*. Corrigió un problema de compilación bajo DJGPP.
• 3.9.40: Henrik Stokseth añadió soporte de fetch_mode_list() para VBE/AF.
• 3.9.40: Robert J. Ohannessian reescribió el mecanismo de obtención de capacidad
de la CPU y añadió algunas nuevas banderas.
• 3.9.40: Eric Botcazou corrigió varios problemas del cursor de ratón bajo Windows.
Actualizó la documentación sobre drivers DIGI_DIRECTX.
• 3.9.40: Javier Gonzalez corrigió los flujos de audio bajo Windows.
• 3.9.40: Peter Wang mejoró el driver XDGA2 eliminando scrolls innecesarios, que
además mejoró el rendimiento al requerir menos bloqueos y desbloqueos. La
corrección original era de Michael Bukin.
• 3.9.40: Eric Botcazou y Javier Gonzalez añadieron documentación sobre enlazado
estático bajo MSVC/MinGW32.
• 3.9.40: Peter Wang arregló los sonames para las versiones de depuración y trazado
de la librería. También añadió comprobaciones al 'configure' para saber si ld soporta
-export-modules antes de activar los módulos.
• 3.9.40: Annie Testes encontró cadenas ASCII que debían ser convertidas. También
añadió la función pack_fdopen().
• 3.9.40: Robert J. Ohannessian clarificó algunas instrucciones de Dev-C++. Corrigió
el script fix.bat bajo MinGW32/Win2k.
• 3.9.40: Marcel Smit corrigió un fallo de los polígonos con corrección de perspectiva
que se dibujaban perpendiculares a la cámara. (dz=0)
• 3.9.40: Peter Wang hizo estática install_timer_int. También movió
allegro_404_char a la API pública.
• 3.9.40: Laurence Withers añadió documentación sobre allegro_404_char.
• 3.9.40: Eric Botcazou corrigió un pequeño fallo con la auto apertura de los menús.
También corrigió un problema de color en los drivers en modo ventana de Windows
con escritorios de 8 bits.
• 3.9.40: Salvador Eduardos Tropea corrigió declaraciones inline friend con cuerpos.
(problema del gcc 3.0.x)
• 3.9.40: Peter Wang mejoró el comportamiento entre menús que se abren con el
ratón y la navegación con teclado. También aclaró la documentación de ustrtok_r().
• 3.9.40: Henrik Stokseth sustituyó mmxtest con un programa de verificación de
capacidades en ensamblador más completo.
• 3.9.40: Eric Botcazou reactivó la paralelización completa en Pentiums para cinco
rutinas de conversión de color. Aplicó optimizaciones xor vs. mov y %ecx vs. %edx
en lo que se refiere al tamaño del código no MMX. Actualizó la documentación
sobre mouse_accel_factor.
• 3.9.40: Peter Wang eliminó el uso de buffers estáticos por uconvert() en algunos
sitios.
• 3.9.40: David A. Capello hizo que d_menu_proc robe/devuelva el foco cuando sea
activado/desactivado.
• 3.9.40: Henrik Stokseth añadió detección de falta de espacio de entorno al script
fix.bat.
• 3.9.40: Eric Botcazou corrigió un comportamiento no ANSI de la versión C de
usprintf().
• 3.9.40: Seunghwan Ji hizo que makedoc genere ficheros html y rtf correctos en
Coreano.
• 3.9.39: Robert J. Ohannessian añadió las opciones -? y --help al dat.
• 3.9.39: Sven Sandberg y Grzegorz Adam Hankiewicz corrigieron algunos errores en
la documentación.
• 3.9.39: Annie Testes corrigió algunos problemas relacionados con el soporte
unicode.
• 3.9.39: Henrik Stokseth añadió la función interna _al_sane_realloc() con
comportamiento garantizado. Se usó para corregir un agujero de memoria y
actualizó el FAQ.
• 3.9.39: Eric Botcazou y Peter Wang actualizaron la documentación sobre: bits de
atributos de ficheros, request_scroll y request_video_bitmap.
• 3.9.39: Eric Botcazou unificó el uso de temporizadores internos en los drivers de
Windows. También hizo que digitest use el volúmen máximo del mezclador de
Allegro.
• 3.9.39: Paul Hampson mejoró de nuevo el driver de joystick DOS SNESpad.
• 3.9.39: Eric Botcazou rediseñó el mecanismo de bloqueo del driver DGA2.
También corrigió algunos agujeros de memoria.
• 3.9.39: Peter Wang añadió soporte para obtener modos de vídeo disponibles en los
drivers X11 y DGA a pantalla completa.
• 3.9.39: Robert J. Ohannessian corrigió el código de masked blit SSE para 16 bits y
eliminó instrucciones no usadas en otros blitters.
• 3.9.39: Salvador Eduardos Tropea añadió algunos arreglos para GCC 3.x.
• 3.9.39: Peter Wang añadió un chequeo para verificar si un módulo listado en
modules.lst existe antes de intentar cargarlo.
• 3.9.39: Charles Wardlaw hizo que alert/alert3 usen fondo transparente para la
etiqueta de texto.
• 3.9.39: Eric Botcazou añadió la función flush_config_file() al API. También añadió
el método hfill() a la estructura GFX_VTABLE.
• 3.9.39: Peter Wang corrigió algunos agujeros de memoria.
• 3.9.39: Eric Botcazou arregló dos warnings de compilación con gcc >; 2.95.
• 3.9.39: Johan Peitz contribuyó el icono 'Alex the Allegator'.
• 3.9.39: Angelo Mottola corrigió el fallo de pantalla completa segura y
fetch_mode_list() para BeOS.
• 3.9.39: Peter Wang actualizó la función fetch_mode_list() de los drivers XDGA2 y
SVGAlib.
• 3.9.39: Henrik Stokseth reescribió la API de listas de modos, actualizó el código y
la documentación.
• 3.9.39: Grzegorz Adam Hankiewicz actualizó todas las URLs en la documentación
de Allegro.
• 3.9.39: Eric Botcazou corrigió el script cmplog para perl 5.6.1.
• 3.9.39: Peter Wang añadió una pregunta al FAQ.
• 3.9.39: Peter Wang corrigió el subsistema de sonido que accidentalmente estropeó
al introducir módulos dinámicos.
• 3.9.39: Eric Botcazou corrigió un warning de compilación. También añadió soporte
de escritorios 8-bit para el driver windows en ventana. Corrigió los desplazamientos
en los conversores de 8-bit. Corrigió un fallo en la rutina de conversión de color 8-
>;8.
• 3.9.39: Javier Gonzalez contribuyó soporte de looping bidireccional para el driver
directsound.
• 3.9.39: Robert J. Ohannessian y Henrik Stokseth hicieron una gran actualización de
las instrucciones de instalación para Mingw32.
• 3.9.39: Eric Botcazou limpió la información de versión de la dll de windows y
permitió que los makefiles de windows usen reglas implícitas con algunos objetivos.
Corrigió un problema de compilación con MSVC.
• 3.9.39: Henrik Stokseth añadió soporte para crear RPMs con SuSE Linux.
• 3.9.39: Peter Wang corrigió algunos errores pequeñísimos. Corrigió el makefile
para unix. Corrigió la desactivación de módulos dinámicos.
• 3.9.39: Eric Botcazou y Grzegorz Adam Hankiewicz terminaron la traducción del
fichero allegro.spec.
• 3.9.39: Eric Botcazou reañadió una pregunta del FAQ sobre problemas de versiones
con DirectX.
• 3.9.39: Grzegorz hizo de fbcon un módulo.
• 3.9.39: Peter Wang quitó allegro-enduser.spec porque ya no hace falta. También
contribuyó una reescritura del fichero allegro.spec, y actualizó los scripts para
generar el rpm. El nuevo fichero allegro.spec está basado en uno que contribuyó
Osvaldo Santana Neto. Peter también permitió al configure pasar parámetros a
allegro-config (para los módulos). Ahora _unix_find_resource también busca en
/usr/[local/]share/allegro los ficheros .dat.
• 3.9.39: Javier Gonzalez contribuyó soporte de reproducción de sonidos hacia atrás
al driver directsound.
• 3.9.39: Eric Botcazou corrigió un problema con la reproducción hacia atrás del
programa digitest.
• 3.9.39: Salvador Eduardos Tropea hizo una pequeña actualización de la sección
cygwin de readme.mgw.
• 3.9.39: Peter Wang corrigió un problema con el make BSD y los separadores de
deirectorio Mac ':'. Documentó la variable gfx_cardw.
• 3.9.39: Sven Sandberg corrigió un molesto efecto colateral que ocurría al tener
clear() como función inline en Watcom.
• 3.9.39: Laurence Withers corrigió un fallo que colgaba el selector de modos de
vídeo.
• 3.9.39: Peter Wang quitó la parte asíncrona SIGIO dado que no es necesaria cuando
se usan pthreads. Actualizó la documentación para mencionar los módulos
dinámicos. Añadió una opción al configure para desactivar la compilación con
pthreads.
• 3.9.39: Burton Radons corrigió un fallo en su blender dissolve.
• 3.9.39: Eric Botcazou corrigió un fallo de los menús causado por la auto-apertura.
• 3.9.39: Henrik Stokseth actualizó los makefiles para que usen -mcpu=pentium en
vez de la opción deprecada -mpentium del gcc. También hizo que los scripts de
empaquetado ejecuten autoconf y borren ficheros ocultos o adicionales.
• 3.9.39: Eric Botcazou limpió el código de sonido de windows. También clarificó el
código básico de las funciones de menús. Corrigió un problema con unicode.
Eliminó las referencias a ALLEGRO_NO_FINDFIRST. Añadió una interfaz
unificada al_find*(). Hizo una traducción portuguesa del antiguo fichero portugués
(Br). Arregló algunos ficheros de configuración de teclado. Cambió los
delimitarores de fin de línea de pl.cfg a \r\n.
• 3.9.39: Grzegorz Godlewski contribuyó una localización al Polaco. También añadió
soporte para tablas altgr mayores y menores.
• 3.9.39: Eric Botcazou corrigió un fallo de la utilidad keyconf causado por la
separación en secciones.
• 3.9.38: Robert J. Ohannessian añadió lo siguiente al conversor de colores: rutinas de
copia de color necesarias en el port BeOS, soporte para conversión cruzada entre
colores de 15 y 16 bits, soporte para conversiones a 8 bits, soporte para rectángulos
de cualquier anchura y añadió dos nuevas rutinas MMX.
• 3.9.38: Henrik Stokseth reescribió get_gfx_mode_list() e igualmente el selector de
modo para que use esta rutina. También añadió la función fetch_mode_list() para
los drivers DirecX, VGA, Mode-X y Xtended.
• 3.9.38: Angelo Mottola corrigió problemas con SMP en el port BeOS.
• 3.9.38: Eric Botcazou corrigió algunos problemas en el código no MMX del
conversor de colores.
• 3.9.38: Sven Sandberg mejoró spline() para DRAW_MODE_TRANS.
• 3.9.38: Peter Wang renombró clear() a clear_bitmap(). clear() todavía existe por
razones de compatibilidad hacia atrás.
• 3.9.38: Stephan Roh hizo que el generador de fractales funcione en procesadores no
Intel.
• 3.9.38: Eric Botcazou hizo un modo de cambio de dispositivo válido de
SWITCH_NONE bajo DOS.
• 3.9.38: Angelo Mottola hizo que el port BeOS use las nuevas rutinas unificadas de
conversión de colores.
• 3.9.38: Peter Wang añadió un chequeo para ver si el dispositivo de visualización es
local bajo X11.
• 3.9.38: Eric Botcazou y Sven Sandberg arreglaron la compilación con Watcom
10.6.
• 3.9.38: Elias Pschernig contribuyó un adjuntador de recursos de iconos para el port
Windows y añadió soporte para librerías compartidas bajo BeOS.
• 3.9.38: Angelo Mottola añadió la utilidad bfixicon.
• 3.9.38: Stephan Roh hizo que el tiempo nativo de Allegro tenga el formato de
time_t ANSI.
• 3.9.38: Peter Wang añadió la función ustrtok_r().
• 3.9.38: Robert J. Ohannessian optimizó algunos masked_blits con instrucciones
SSE.
• 3.9.38: Angelo Mottola corrigió un error en la salida de los flujos de audio y
máquinas SMP, y añadió soporte de triple buffering al port BeOS.
• 3.9.38: Angelo Mottola añadió soporte fetch_mode_list() al driver a pantalla
completa de BeOS.
• 3.9.38: Eric Botcazou cambió el escema de aceleración de ratón bajo Windows.
• 3.9.38: Peter Wang añadió soporte fetch_mode_list() al driver svgalib.
• 3.9.38: Peter Wang añadió temporizadores pthread y eliminó las dependencias de
SIGALRM.
• 3.9.38: Henrik Stokseth añadió detección de Windows XP.
• 3.9.38: Andreas Kluge corrigió un fallo de ajuste de volumen en DOS para el driver
Soundscape.
• 3.9.38: Angelo Mottola reescribió el driver de sonido BeOS para que use la clase
BSoundPlayer.
• 3.9.38: Robert J. Ohannessian añadió detección SSE y SSE2.
• 3.9.38: Connelly Barnes corrigió un fallo de panoramización con DirectSound.
• 3.9.38: Eric Botcazou añadió soporte de cambio de tarea al programat test.
• 3.9.38: Eric Botcazou modificó el mecanismo de cambio de tarea bajo Windows.
• 3.9.38: Angelo Mottola añadió soporte de cambio de tarea al driver a pantalla
completa de BeOS y arregló y limpió otras cosas.
• 3.9.38: Henrik Stokseth añadió código para conseguir más información del SO bajo
Unix.
• 3.9.38: Nimrod Abing corrigió un error en las rutinas de configuración relacionado
con la sección NULL.
• 3.9.38: Eric Botcazou arregló un cuelgue del driver en ventana de Windows en
sistemas rápidos.
• 3.9.38: Ronaldo Hideki Yamada hizo grandes cambios del port PowerMac y añadió
un driver midi.
• 3.9.38: Henrik Stokseth generalizó el soporte de optimizaciones específicas de
procesadores en algunos ficheros makefile.
• 3.9.38: Evert Glebbeek puso set_gfx_mode a dieta y añadió la variable de
configuración para indicar la tarjeta a usar con
GFX_AUTODETECT_WINDOWED.
• 3.9.38: Robert J. Ohannessian hizo que blit no convierta entre profundidades de
color en bitmaps de vídeo (para AllegroGL).
• 3.9.38: Peter Wang hizo que fix_filename_slashes() maneje ambos tipos de
separadores.
• 3.9.38: Grzegorz Adam Hankiewicz implementó un parámetro de makedoc para
verificar líneas de documentación largas (>;77).
• 3.9.38: Owen Rudge contribuyó un script de recursos para la versión DLL.
• 3.9.38: Sven Sandberg hizo las funciones de rotación más rápidas, más precisas y
ahora funcionan con cualquier bitmap. Además eliminó rotate_scaled_sprite_flip().
• 3.9.38: Angelo Mottola añadió soporte fetch_mode_list() para DGA2.
• 3.9.38: David A. Capello hizo que el programa test use polígonos transparentes.
• 3.9.38: Owen Rudge constribuyó el script mkdata.bat.
• 3.9.38: Grzegorz Adam Hankiewicz añadió reload_config_texts().
• 3.9.38: Eric Botcazou añadió una mejora al mecanismo de construcción para los
ficheros que definen la exportación de las DLL.
• 3.9.38: Eric Botcazou añadió un nuevo ejemplo unicode y realizo toneladas de
pequeños arreglos.
• 3.9.37: Johan Peitz corrigió y mejoró el driver Win32 de joystick.
• 3.9.37: Sven Sandberg añadió teclas Ctrl + cursor a d_edit_proc().
• 3.9.37: Eric Botcazou cambió el color de máscara a fucsia en el driver overlay de
Windows.
• 3.9.37: Eric Botcazou deshizo algunos cambios realizados al núcleo de
temporización de la última versión porque causaban problemas con el reproductor
MIDI, y quitó el driver temporización Windows multihilo.
• 3.9.37: Henrik Stokseth actualizó el código de detección de SO, y añadió la variable
os_multitasking.
• 3.9.37: Eric Botcazou corrigió un problema en las rutinas de configuración, donde
los valores en la sección NULL estaban ocultando entradas duplicadas en otras
secciones.
• 3.9.37: Eric Botcazou hizo que el programa setup use funciones Unicode.
• 3.9.37: Henrik Stokseth unificó los scripts fix*, y les añadió opciones.
• 3.9.37: Peter Wang añadió soporte de carga de módulos dinámicamente bajo Unix.
Los drivers SVGAlib, ALSA digital, ALSA MIDI, ESD y DGA2 serán compilados
como módulos cuando sea posible. Esto elimina dependencias externas en la librería
principal y mejora la transportabilidad de binarios bajo Linux.
• 3.9.37: Eric Botcazou hizo algunos cambios y correcciones a las funciones de
cadenas Unicode, y su uso en la librería. Las funciones antiguas ahora se comportan
exáctamente como sus equivalentes libc, mientras que las nuevas funciones (las que
llevan 'z') se comportan de forma más razonable. Este cambio afecta la mayoría del
código que usa funciones Unicode.
• 3.9.37: Bertrand Coconnier cambió la API de render de escenas integrada
reciéntemente, corrigió un fallo, y añadió un nuevo programa de ejemplo. El cambio
del API afecta a todo el código que use funciones de escena.
• 3.9.37: Laurence Withers envolvió el registro de tipos de bitmaps en un constructor.
Donde éstos estén disponibles, se debería reducir el tamaño del ejecutable al usar
enlace estático (a no ser que use los cargadores de bitmaps, por supuesto).
• 3.9.37: Ben Davis modificó la escala de set_volume_per_voice. Por favor mire la
documentación si la ha usado anteriormente.
• 3.9.37: Eric Botcazou parcheó un fallo del ratón bajo DOS en Win2k.
• 3.9.37: Eric Botcazou añadió soporte del modo VGA 13h bajo DirectX 5 y
versiones posteriores.
• 3.9.37: Henrik Stokseth añadió la función get_gfx_mode_list(), y su
implementación para el driver VESA.
• 3.9.37: Eric Botcazou y Annie Testes se esforzaron por evitar desbordamientos de
buffer (particularmente aquellos que tienen que ver con funciones Unicode).
• 3.9.37: Eric Botcazou corrigió un fallo con los mickeys del ratón e hizo limpieza en
el subsystema de entrada del usuario bajo Windows.
• 3.9.37: Eric Botcazou cambió dos cosas en lo referente al manejo del color 0 en
modos de paleta.
• 3.9.37: Eric Botcazou añadió una opción a las herramientas grabber y dat para
preservar la transparencia.
• 3.9.37: Eric Botcazou corrigió un cuelgue cuando se usaba alt-tab en un programa
con page flipping bajo Windows.
• 3.9.37: Peter Wang añadió added gui_menu_draw_menu y
gui_menu_draw_menu_item para permitir personalizar el aspecto de los menús de
la interfaz gráfica (hasta cierto punto).
• 3.9.37: Angelo Mottola añadió soporte para las nuevas constantes
GFX_AUTODETECT_FULLSCREEN y GFX_AUTODETECT_WINDOWED,
sobre las cuales todos nos pusimos de acuerdo de todo corazón :-)
• 3.9.37: Eduard Bloch hizo que las variables de configuración que existen pero están
vacías devuelvan el valor por defecto.
• 3.9.37: Elias Pschernig añadió el modo COLORCONV_KEEP_TRANS.
• 3.9.37: Henrik Stokseth añadió soporte para compilar con Cygwin. Funciona en
modo compatibilidad con Mingw.
• 3.9.37: Angelo Mottola hizo que los submenús de la interfaz automáticamente se
abran cuando el ratón ha estado sobre ellos el tiempo suficiente. (Esto es un viejo
parche que finalmente se ha aceptado.) Eriq hizo algunas modificaciones
relacionadas más tarde.
• 3.9.37: Eric Botcazou hizo que clear_keybuf() no limpie el array key[].
• 3.9.37: Sven Sandberg añadió la opción --quick a los scripts fix.
• 3.9.37: Angelo Mottola hizo _un montón_ de trabajo en el port QNX (demasiado
como para documentarlo aquí).
• 3.9.37: Eric Botcazou hizo que el código de conversión ensamblador Win32 esté
disponible para otros ports, y añadió algunos conversores más. Isaac Cruz añadió
uno también.
• 3.9.37: Eric Botcazou restructuró el formato del fichero de configuración. Algunas
variables que no tenían sección, están ahora en una.
• 3.9.37: George Foot añadió un sistema multihilo para manejar eventos asíncronos,
en vez de usar SIGALRM (bajo Unix).
• 3.9.37: George Foot corrigió algunos problemas con pack_fgets().
• 3.9.36: Eric Botcazou hizo que set_keyboard_rate(0, 0) desactive la repetición del
teclado, tal y como indica la documentación.
• 3.9.36: Annie Testes añadió ganchos font_height, render_char y char_length a la
tabla FONT_VTABLE.
• 3.9.36: Eric Botcazou hizo algunos cambios menores relacionados con AllegroGL
en el código de manipulación de ventana, y corrigió dos fallos menores del ratón
que Javier Gonzalez había encontrado (ambos bajo Windows).
• 3.9.36: Eric Botcazou añadió la función get_desktop_resolution() para Windows y
X. Joshua Haberman añadió la versión BeOS.
• 3.9.36: Angelo Mottola comenzó un port a QNX.
• 3.9.36: Robert Ohannessian corrigió el órden src/dest en los blenders aditivos.
• 3.9.36: Eric Botcazou mejoró el soporte de ventanas externas en Windows.
• 3.9.36: Peter Wang actualizó el driver SVGAlib para la versión 2.
• 3.9.36: Peter Wang añadió una versión a pantalla completa del driver X-Window. El
driver original era de Benjamin Joel Stover.
• 3.9.36: Peter Wang hizo que el grabber use file_select_ex(). Esto está aquí sólo para
que no se sorprenda :-)
• 3.9.36: Eric Botcazou corrigió pequeños fallos del código DirectSound de entrada.
• 3.9.36: Eric Botcazou corrigió el estado NumLock bajo X, que antes no se
correspondía con el de los LEDs.
• 3.9.36: Eric Botcazou reactivó el temporizador multi-hilo bajo Windows.
• 3.9.36: Eric Botcazou y Javier Gonzalez hicieron que el sistema de repetición del
teclado sea más eficiente.
• 3.9.36: Eric Botcazou corrigió algunos blitters en ensamblador, y un fallo en la
alteración de la velocidad de los temporizadores.
• 3.9.36: Peter Wang hizo que el teclado numérico devuelva valores ASCII / * - +
incluso cuando NumLock está desactivado, en la consola Linux.
• 3.9.36: Ronaldo Hideki Yamada hizo una grán actualización del port de Mac,
incluyendo algunos ficheros PPC nuevos.
• 3.9.36: El driver GGI ha sido eliminado, debido a que no es capaz de funcionar. No
será soportado hasta que alguien lo reescriba.
• 3.9.36: Eric Botcazou corrigió un problema con el driver GDI cuando se compilaba
con MSVC.
• 3.9.36: Algunas correcciones MIDI por Javier Gonzalez y Eric Botcazou.
• 3.9.36: Grzegorz Adam Hankiewicz mejoró la función de tratamiento de líneas del
fichero fb.modes para el driver fbcon.
• 3.9.36: Grzegorz Adam Hankiewicz cambió el comportamiento de GFX_SAFE.
Esto significa que "set_gfx_mode(GFX_SAFE, ...)" ahora devuelve un error si no es
capaz de entrar en modo gráfico, tal y como cualquier otro driver.
• 3.9.36: Eric Botcazou corrigió el control de volúmen bajo Windows.
• 3.9.36: Eric Botcazou añadió compatibilidad con DirectX 3.
• 3.9.36: Nick Kochakian añadió rutinas de entrada al driver DirectSound. También
fue modificado por Javier Gonzalez.
• 3.9.35: Eric Botcazou hizo que Windows recupere el volúmen original del sonido
tras la finalización de un programa Allegro.
• 3.9.35: Eric Botcazou corrigió el looping de sonidos del driver DirectSound.
• 3.9.35: Grzegorz Adam Hankiewicz corrigió algunos problemas de color en el juego
demo.
• 3.9.35: Angelo Mottola implementó el gancho de botón de cierre para X11.
• 3.9.35: Eric Botcazou corrigió _el_ fallo de teclado de Windows 2000.
• 3.9.35: Eric Botcazou hizo algunos cambios al mecanismo de bloqueo/ desbloqueo
del port Windows.
• 3.9.35: Laurence Withers hizo que algunos módulos eviten dependencias de
enlazado.
• 3.9.35: Javier Gonzalez añadió soporte para el botón de cierre de Windows.
• 3.9.35: Eric Botcazou mejoró el manejo del ratón con el driver GFX_GDI, y
corrigió también otros fallos del ratón.
• 3.9.35: Peter Wang hizo que set_mouse_sprite(NULL) regenere el bitmap de la
flecha por defecto (usando la paleta actual).
• 3.9.35: Eric Botcazou hizo que las primitivas aceleradas por hardware se detengan
cuando el usuario cambia a otra aplicación en Windows.
• 3.9.35: Tom St Denis corrigió el recorte de objetos transparentes.
• 3.9.35: Eric Botcazou y Javier Gonzalez mejoraron el cambio a otras aplicaciones
en Windows y otras cosas.
• 3.9.35: Peter Wang hizo que el driver de joystick para Linux use las constatnes
estándar.
• 3.9.35: Sven Sandberg cambió la API de Z-buffer.
• 3.9.35: Peter Wang hizo que el sprite del ratón por defecto sea independiente de la
paleta en modos de 8bpp.
• 3.9.35: Bertrand Coconnier añadió documentación sobre la fusión de P3D.
• 3.9.35: Angelo Mottola corrigió desktop_color_depth() y añadió soporte para el
botón de cierre del port BeOS.
• 3.9.35: Ben Davis añadió el esqueleto de set_window_close_button() y
set_window_close_hook().
• 3.9.35: Peter Wang hizo públicas las variables mouse_sprite, mouse_x_focus y
mouse_y_focus.
• 3.9.35: Robert Ohannessian y Javier Gonzalez corrigieron el fallo de limpieza de
subbitmaps.
• 3.9.35: Peter Wang renombró GFX_XDFS a GFX_XDGA_FULLSCREEN.
• 3.9.35: Henrik Stokseth actualizó el sistema de compilación cruzada.
• 3.9.35: Tomohiko Sugiura añadió algunas teclas y renombro algunas teclas JP.
• 3.9.35: Eric Botcazou añadió una interfaz DirectDraw2, con soporte de frecuencias
de refresco.
• 3.9.35: Bertrand Coconnier fusionó la librería P3D de Calin Andrian.
• 3.9.35: Javier Gonzalez hizo que allegro_message() use el título de
set_window_title() bajo Windows.
• 3.9.35: Andreas Kluge corrigió los fallos de división en la clase de punto fijo.
• 3.9.35: Stepan Roh documentó los bits FA_*.
• 3.9.35: Peter Wang añadió ganchos para permitir cambiar el aspecto de los diálogos
estándar.
• 3.9.35: Peter Wang cambió el comportamiento y posicionado de las ventanas bajo
X.
• 3.9.35: David A. Capello hizo que dotted_rect() evite cambios de banco.
• 3.9.35: Eric Botcazou corrigió un bloqueo bajo Windows que ocurría
bloqueando/desbloqueando bitmaps con la CPU muy cargada. Recibió ayuda de
Javier Gonzalez para encontrar el fallo.
• 3.9.35: Stepan Roh corrigió un fallo con la constante FA_RDONLY bajo Unix.
• 3.9.35: Eric Botcazou hizo limpieza del subsistema gráfico de Windows.
• 3.9.35: "Sask Allegro" añadió soporte para más de dos joysticks en el port
Windows.
• 3.9.34: Ben Davis hizo que la aspa en modos ventana bajo Windows no simule la
tecla Esc, en preparación para un nuevo comportamiento (de la próxima WIP).
• 3.9.34: Laurence Withers corrigió un problema con los acentos en keyconf.
• 3.9.34: Javier Gonzalez añadió DIGMID a la lista Windows de controladores MIDI.
• 3.9.34: Eric Botcazou hizo limpieza en el subsistema DirectDraw.
• 3.9.34: Eric Botcazou hizo que el controlador overlay DirectDraw funcione con
código que use page flipping y triple buffering, entre otras cosas.
• 3.9.34: Bertrand Coconnier mejoró la precisión subtexel en la aplicación de
texturas.
• 3.9.34: Javier Gonzalez corrigió la velocidad de movimiento del ratón bajo
Windows.
• 3.9.34: Ben Davis adaptó las funciones de polígonos para que manejar vértices
compartidos, y modificó y clarificó el alineamiento de coordenadas de texturas en el
código y en la documentación.
• 3.9.34: Grzegorz Adam Hankiewicz escribió la documentación de las funciones
Unicode, adaptando documentación de djgpp y gcc.
• 3.9.34: Eric Botcazou corrigió un problema con el triple buffering con el driver
DirectDraw acelerado por hardware.
• 3.9.34: Henrik Stokseth añadió soporte para compilar versiones de otras plataformas
en el proceso de compilación de mingw32.
• 3.9.34: Grzegorz Adam Hankiewicz actualizó más ejemplos para GFX_SAFE.
• 3.9.34: Ben Davis añadió set_volume_per_voice(), hizo que las voces silenciosas
continúen siendo reproducidas y corrigió otros fallos menores.
• 3.9.34: Ben Davis corrigió un fallo en create_rgb_table().
• 3.9.34: Angelo Mottola añadió rutinas para cambio de modo para BeOS y corrigió
algunos fallos.
• 3.9.34: Laurence Withers Actualizó la documentación sobre `const'.
• 3.9.34: Ronaldo Hideki Yamada contribuyó la versión macintosh de Allegro.
• 3.9.34: Grzegorz Adam Hankiewicz cambió y documentó el nuevo comportamiento
de GFX_SAFE (ahora la profundidad del color es indefinida), actualizó el driver
fbcon para aprovechar esto, y actualizó los programas de ejemplo.
• 3.9.34: Peter Pavlovic corrigió un fallo causado por el escalado del selector de
ficheros.
• 3.9.34: Bertrand Coconnier corrigió fallos relacionados con poly3d(); quitó
versiones C nunca llamadas de las funciones por scanline de POLYTYPE_FLAT y
versiones hicolor/truecolor de POLYTYPE_GCOL; hizo que las rutinas clip3d() y
clip3d_f() funcionen con polígonos con Z-buffer.
• 3.9.34: Stepan Roh añadió la versión C de masked_stretch_blit().
• 3.9.34: Angelo Mottola trabajó más en la versión BeOS: aceleración por hardware
(rect, hline, vline, clear_to_color, blit); correción del ratón en modos de ventana;
desktop_color_depth(); yield_timeslice();
• 3.9.34: Peter Wang actualizó retroactivamente los ficheros CHANGES y
AUTHORS desde la antigua 3.9.33 hasta el presente usando logs de CVS y archivos
de emails, y casi con toda seguridad trastocó algo.
• 3.9.34: Angelo Mottola añadió un driver en ventana para BeOS (originalmente
escrito por Peter Wang), un driver MIDI para BeOS, soporte de la ruedecilla del
ratón para BeOS y realizó muchas otras correcciones y cambios al código BeOS y la
documentación.
• 3.9.34: Laurence Withers corrigió la salida de fuentes de dat2s para el nuevo
subsistema de fuentes.
• 3.9.34: Peter Wang hizo al driver SVGAlib más robusto.
• 3.9.34: Peter Wang cambió la forma de seleccionar los protocolos Intellimouse en la
consola Linux.
• 3.9.34: Eric Botcazou añadió file_select_ex y revirtió file_select al antiguo
comportamiento.
• 3.9.34: Laurence Withers añadió la función ugetcx().
• 3.9.34: Laurence Withers diseñó e implementó una nueva estructura FONT, que
debería proveer muchas ventajas sobre la antigua.
• 3.9.34: Eric Botcazou hizo más correcciones al código Windows.
• 3.9.34: Bertrand Coconnier añadió el render de polígonos 3D por Z-buffer,
(derivado de la librería P3D de Calin Andrian), y un ejemplo para ésto.
• 3.9.34: Michael Bukin añadió la posibilidad de personalizar las equivalencias
keycode a scancode bajo X.
• 3.9.34: Peter Wang añadió soporte de ruedecilla del ratón a d_textbox_proc y
d_slider_proc, e hizo que el selector de ficheros pueda reescalarse.
• 3.9.34: Tom Fjellstrom añadió el driver MIDI ALSA.
• 3.9.34: Eric Botcazou hizo algunos cambios al controlador de Windows en modo
ventana.
• 3.9.34: Grzegorz Adam Hankiewicz actualizó la documentación y el programa
makedoc para producir mejor salida .texi. La nueva versión funciona muy bien con
el programa texi2dvi, que produce salida independiente del dispositivo lista para ser
impresa. También documentó los nuevos comandos unix del makefile.
• 3.9.34: George Foot añadió la opción --env al script allegro-config.
• 3.9.34: Benjamin Stover corrigió cosas con argumentos variables en unicode.c y
añadió un remedio a los defines necesarios en fbcon.c.
• 3.9.34: Robin Burrows añadió un driver de sonido Windows waveOut.
• 3.9.34: Eric Botcazou cambió desktop_color_depth() para Windows.
• 3.9.34: Angelo Mottola añadió soporte para cambio de líneas y refresco al driver
DGA2.
• 3.9.34: Bertrand Coconnier añadió subdivisión de scanlines y corrigió el dibujado
de polígonos 3D.
• 3.9.34: Angelo Mottola añadió el driver de joystick para BeOS.
• 3.9.34: Angelo Mottola añadió el driver DGA2.
• 3.9.34: Robin Burrows añadió un driver Windows que usa el mezclador de Allegro.
• 3.9.34: Stepan Roh añadió un remedio a la rutina fceil definida en las cabeceras Irix.
• 3.9.34: Michael Bukin cambió la forma de limpiar una pantalla DGA.
• 3.9.34: Tomohiko Sugiura añadió un controlador sidewinder más agresivo.
• 3.9.34: Tomohiko Sugiura añadió tres teclas japonesas.
• 3.9.34: Stepan Roh hizo las funciones C correctas según `const'.
• 3.9.34: Bertrand Coconnier corrigió el blending en las funciones atex_lit de
scanlines.
• 3.9.34: Michael Bukin modificó text_mode para que vuelva al modo previo.
• 3.9.34: Peter Pavlovic corrigió la visualización de la barra del grabber y mejoró el
scroll de los objetos GUI.
• 3.9.34: anarko hizo que los objetos GUI recuperen el modo de texto.
• 3.9.34: Laurence Withers añadió un gancho para destruir fuentes.
• 3.9.34: Vincent Penquerc'h modificó los eventos de pulsación/soltado del ratón para
que tengan mayor prioridad que los eventos de doble click.
• 3.9.34: Eric Botcazou mejoró el control del mapa de colores en XDGA.
• 3.9.34: Robin Burrows contribuyó nuevo código de page flipping para el subsistema
DirectDraw, que ahora funciona en cualquier tarjeta de vídeo.
• 3.9.33: Henrik Stokseth actualizó el makefile de mingw32, la documentación y
mandó otras correcciones y actualizaciones. Ya no necesitará otra vez MSVC para
compilar las DLLs de Allegro. ;o)
• 3.9.33: Peter Puck contribuyó actualizaciones al código win32 de Allegro, con lo
que consiguí que la versión mingw32 funcione completamente.
• 3.9.33: Michael Bukin cambió el manejo de la autorepetición bajo X, el manejo de
sched_yield bajo Unix, corrigió _add_exit_func, y añadió una lista de diálogos
activos al GUI.
• 3.9.33: Vincent Penquerc'h aceleró bastante la versión C de la rutina de dibujado de
sprites RLE.
• 3.9.33: Peter Wang mejoró la carga de paletas TGA.
• 3.9.33: Laurence Withers hizo más funciones correctas según `const'.
• 3.9.33: Isaac Cruz movió el bloqueo de bitmaps bajo Windows aun fichero .S
separado, cambió la lógica de actualización del controlador en modo ventana, y
añadió una implementación acelerada de vline.
• 3.9.33: Stephen Kittelson corrigió un faloo en pckeys.c, y cambió los valores ASCII
devueltos por algunas extrañas combinaciones de teclas.
• 3.9.33: Peter Wang hizo que algunas funciones fuesen correctas con el contexto de
la palabra reservada 'const'.
• 3.9.33: Peter Pavlovic hizo modificaciones estéticas al sistema de menús de la
interfaz gráfica del usuario.
• 3.9.33: Javier Gonzalez sugirió que los diálogos de selección de modo y fichero
usasen popup_dialog.
• 3.9.33: Vincent Penquerc'h añadió el comando install-gzipped-man al makefile,
parcheó algunos controles de EINTR, e hizo que el controlador OSS detectase si el
dispositivo es de 16 bits o nó.
• 3.9.33: Peter Pavlovic modificó el mapa de teclado eslovaco e hizo que el selector
de ficheros detecte las unidades disponibles bajo Windows.
• 3.9.33: Peter Wang añadió sonido (sólo salida) al controlador de BeOS.
• 3.9.33: Sven Sandberg corrigió un fallo en la definición de ustrdup, añadió la
función uwidth_max, contrinuyó la función d_yield_proc, e hizo que varios
diálogos la usasen.
• 3.9.33: Michael Bukin hizo que el controlador DGA limpie la memoria de vídeo y
centre la pantalla cuando no se esté a pantalla completa.
• 3.9.33: Eduard Bloch sugirió mejores métodos para encontrar el ejecutable bajo
Unix.
• 3.9.33: Andrew Geers añadió sprites rotados e invertidos.
• 3.9.33: George Foot hizo que el makefile de Unix funcione con usuarios que no son
el superusuario.
• 3.9.33: Grzegorz Adam Hankiewicz hizo que los ficheros de configuración de
lenguajes estén forzados a minúsculas.
• 3.9.33: Grzegorz Adam Hankiewicz añadió documentación para findfirst(),
findnext(), y findclose(), y corrigió la documentación de get_executable_name().
• 3.9.33: Stephan Roh contribuyo parches para compilar Allegro bajo IRIX.
• 3.9.33: John Harger hizo cambios para mejorar la estabilidad de AllegroGL bajo
Windows.
• 3.9.33: Sven Sandberg corrigió un fallo en la versión C a 16bpp del blit con
escalado.
• 3.9.33: George Foot corrigió un fallo en las rutinas de blit con máscara en 8bpp para
i386, notificado por Damian Yerrick.
• 3.9.33: Eduard Bloch solucionó un congelamiento en el código de detección de
ESD.
• 3.9.33: Vincent Penquerc'h añadió eventos de pulsación/soltura de los botones del
ratón.
• 3.9.33: Peter Wang solucionó un conflicto con SVGAlib.
• 3.9.33: Vincent Penquerc'h añadió las propiedades XCRP e YCRP a los objetos
bitmap almacenados en ficheros de datos.
• 3.9.33: Vincent Penquerc'h hizo que el sistema GUI no mande mensajes
MSG_DRAW a los objetos ocultos.
• 3.9.33: Chris La Mantia apuntó que su código de textprintf_right, de alguna forma
había mutado.
• 3.9.33: Peter Wang añadió una solución al fallo de algunos servidores X al indicar
movimiento del ratón.
• 3.9.33: Eric Botcazou alteró el código DGA para que trabaje mejor en modos de
32bpp.
• 3.9.33: Daniel Nilsson afinó exstars y exlights.
• 3.9.33: Isaac Cruz corrigió un fallo grave con el bloqueo de subbitmaps, y añadió
soporte para desktop_color_depth y yield_timeslice bajo Windows.
• 3.9.33: Peter Cech hizo que uisspace() reconozca carácteres no ASCII de espaciado
• 3.9.32: S.Sakamaki añadió una función para controlar la velocidad de refresco de la
pantalla con el controlador DOS VESA 3.0 (esto podría estar soportado por otros
controladores si alguien lo implementa).
• 3.9.32: S.Suzuki añadió controladores DOS para las tarjetas con interfaz para
joysticks IF-SEGA /PCI, /PCI2, e /ISA
• 3.9.32: Fabrizio Gennari añadió controladores DOS para joysticks multisistema con
conectores de 9 pins (Atari, Commodore 64, MSX).
• 3.9.32: Peter Pavlovic mejoró el soporte de carácteres acentuados en el controlador
de teclado.
• 3.9.32: Sven Sandberg optimizó el scroll de la lista de elementos del GUI para
ignorar redibujados si no puede mantener la velocidad de actualización.
• 3.9.32: Olly Betts trabajó en hacer que se pueda compilar la versión djgpp desde
Linux.
• 3.9.32: Isaac Cruz mejoró el driver ddraw en modo ventana, añadiendo soporte para
diferentes conversiones de color entre profundidades distintas.
• 3.9.32: Vincent Penquerc'h añadió una función al grabber para actualizar una
selección.
• 3.9.32: muchas correcciones de varias personas.
• 3.9.32: zipup.sh ahora genera dependencias usando únicamente herramientas
estándar de Unix y gcc, por lo que puede configurarse para soportar todas las
plataformas sin la necesidad de tener esos compiladores (es decir, puedo crear
dependencias para Watcom, BeOS y Mingw32 desde mi máqina Linux). No
obstante, esto requiere algo de cooperación por parte de las plataformas indicadas:
necesitan activar su propio comando "make depend" para sobreescribir los defines
estándar del gcc, y envolver cualquier cabecera no estándar con "#ifndef
SCAN_DEPEND".
• 3.9.32: corregido (espero :-) el fallo con las zonas temporales no GMT del código
de actualización de ficheros de datos.
• 3.9.32: reescritura de la rutina Unicode usprintf() para obtener ayuda de la libc
convirtiendo datos en coma flotante (esto es demasiado difícil para que seamos
capaces de hacerlo nosotros :-)
• 3.9.31: Henrik Stokseth trabajó en una versión nativa de Mingw32. Todavía es
incompleta, y es improbable que funcione ahora ya que hubo otros cambios en el
código Windows desde que empezó. Por el momento esta versión se enlaza
estáticamente, usando makefile.mgs, y makefile.mgw todavía existe para la versión
dependiente de MSVC. El objetivo final es conseguir que la versión nativa crée una
DLL aparte de la versión estática, momento en el cual se podrían mezclar ambos
makefiles en makefile.mgw y borrar makefile.mgs. Oh si, todavía no hay
documentación sobre esta versión nativa.
• 3.9.31: Greg Hackmann contribuyó el port de Borland C++ Builder. Al igual que las
versiones RSXNT y Mingw32, esto es un cliente de la DLL de MSVC, y no es
capaz de compilar Allegro por sí mismo, pero permite crear programas con Allegro
usando el compilador de Borland.
• 3.9.31: Robert Ohannessian añadió optimización para la función clear() de 8 y 16
bits, y Jose Antonio Luque optimizó las rutinas blit() y masked_blit() de 16 bits.
• 3.9.31: Vincent Penquerc'h añadió la función yield_timeslice() (por el momento
sólo implementada bajo DOS y Unix).
• 3.9.31: se añadió la función desktop_color_depth() (por el momento sólo
implementada bajo X: pronto será el turno de la versión Windows).
• 3.9.31: Isaac Cruz añadió soporte para los modos en ventana a diferentes
profundidades de color que el escritorio, y bitmaps de sistema acelerados por
hardware.
• 3.9.31: Jose Antonio Luque mejoró el controlador de joystick de Windows.
• 3.9.31: James Hyman añadió soporte para difuminar imágenes truecolor a modos
con paleta.
• 3.9.31: Chris La Mantia añadió las funciones textout_right(), textprintf_right(),
textprintf_justify().
• 3.9.31: Sven Sandberg añadió la función ustrrchr(), y mejoró usprintf() en el manejo
de grandes números en coma flotante.
• 3.9.31: Peter Pavlovic añadió un mapa de teclado eslovaco y la traducción de los
mensajes de sistema.
• 3.9.31: Manni Heumann corrigió algunos problemas con el mapa de teclado alemán.
• 3.9.31: Michael Bukin mejoró el control de teclado y ratón bajo X, y corrigió
algunos problemas con la compilación en sistemas no GNU.
• 3.9.31: muchas correcciones y ajustes de varias personas (lo siento, mi paciencia
tecleando se ha acabado, por lo que no tendrás la lista completa :-)
• 3.9.31: Peter Wang añadió soporte de entrada para el controlador OSS de Linux.
• 3.9.31: David Kuhling optimizó el código i386/gcc de fsqrt(), y añadió la rutina
fhypot().
• 3.9.30: corregido el fallo de doble XOR que hacía tan fácil la desencriptación de
claves de un fichero de datos. El nuevo código todavía puede leer ficheros
encriptados con el estilo antiguo, pero los datos escritos con esta versión no podrán
ser accedidos por versiones anteriores de Allegro.
• 3.9.30: se hizo posible que la sintaxis de fichero.dat#objeto y load_datafile() y
load_datafile_object() funcionen correctamente en todas las posibles
combinaciones.
• 3.9.30: Vincent Penquerc'h añadió la función scare_mouse_area().
• 3.9.30: se cambió el mecanismo de fijación de superficies DirectX para mejorar el
rendimiento del dibujado acelerado por hardware
• 3.9.30: George Foot mejoró el código Linux de control de los LEDs, e hizo visible
el estado interno del driver X visible vía xalleg.h.
• 3.9.30: se añadió la consideración de EINTR en las rutinas de lectura/escritura.
Espero haber hecho esto correctamente: estaría muy bien que alguien experto en
estas lides pudiese echar un vistazo a file.c.
• 3.9.30: el controlador de ratón ya funciona correctamente bajo Windows en modo
ventana.
• 3.9.30: se corrigieron varios problemas con el cambio primer plano/tarea de fondo
de Windows (las teclas se quedaban presionadas, los temporizadores no se paraban,
y no se estaba informando correctamente de todos los modos de cambio al
programa).
• 3.9.30: se hizo que el controlador de teclado liberase todas las teclas presionadas al
perder el foco de entrada, para evitar que las teclas se quedasen atascadas al cambiar
de ventana con alt+tab.
• 3.9.30: ahora los parámetros del script allegro-lib son compatibles con el estándar
usado por GTK, ESD, etc, y el script se renombró a allegro-config. Esto cambia la
sintaxis para enlazar programas Allegro bajo Unix: lea los detalles de este nuevo
método en readme.uni.
• 3.9.30: George Foot mejoró el sistema de bibliotecas compartidas bajo Unix.
• 3.9.30: Joerg Rueppel añadió la función find_datafile_object().
• 3.9.30: Peter Wang mejoró el driver SVGAlib.
• 3.9.30: Peter Wang mejoró el driver de joystick para Linux.
• 3.9.29: se hizo que el código Windows esté de acuerdo con las otras plataformas en
el tema de cómo deben comportarse los bitmaps de vídeo.
• 3.9.29: se corrigieron algunos problemas con el la ruedecilla del ratón en la versión
Windows.
• 3.9.29: se añadieron las funciones set_write_alpha_blender(), set_add_blender() y
create_blender_table(), y se hizo que la versión de 32 bits de draw_trans_sprite()
pueda usar imágenes origen de 8 bits junto con set_write_alpha_blender(). Aparte
de ser útil en general, usar estas rutinas reduce la longitud del código fuente de mi
programa que compite en el SpeedHack :-)
• 3.9.29: se añadió un comando uninstall al makefile de Linux.
• 3.9.29: ahora el controlador de ratón del servidor X oculta el cursor por software
Allegro cuando el ratón se mueve fuera de la ventana
• 3.9.29: se añadió una emulación simple de vsync() por temporización al código para
X, para que por ejemplo el juego demo de gusanos funcione bien.
• 3.9.29: Isaac Cruz añadió un driver GFX_DIRECTX_WIN.
• 3.9.29: Keith Gerdes hizo algunas mejoras al driver overlay de DirectX.
• 3.9.29: Andrew Geers añadió soporte de scroll al draw_trans_sprite() del grabber
que visualiza imágenes.
• 3.9.29: Peter Wang añadió un driver X DGA alternativo que incluye soporte para
funcionar a pantalla completa.
• 3.9.29: Peter Wang añadió el evento MSG_WHEEL al GUI, e hizo que
d_list_proc() lo use.
• 3.9.29: Lucas Vignoli Reis añadió traducciones de los mensajes y mapa de teclado
en Portugués (Brasil).
• 3.9.29: Peter Wang añadió driver MIDI Linux OSS para sintetizadores de música
FM y soporte de mezclador al driver digital OSS.
• 3.9.29: George Foot añadió scripts para generar diferentes formatos de
distribuciones Linux.
• 3.9.29: Michael Bukin arregló los problemas de portabilidad de quantize.c.
• 3.9.29: se añadió un script zipwin.sh. para crear distribuciones binarias para
Windows, incluyendo un fichero bat que puede generar los programas de soporte de
MSVC sin tener instalada ninguna herramienta GNU.
• 3.9.29: corregido el fallo del color al dibujar una fuente con la versión Windows.
• 3.9.29: se añadieron versiones aceleradas por hardware de rectfill() y hline() a la
versión Windows, y se solucionaron algunos fallos con la aceleración (las funciones
clear no estaban siendo recortadas correctamente, y se indicaba poder hacer
dibujado XOR a pesar de que ni si quiera está soportado).
• 3.9.29: Michael Bukin corrigió el fallo de X cuanado se dibujaba sobre un sub-
bitmap de la pantalla.
• 3.9.28: varias actualizaciones de documentación.
• 3.9.28: se añadió la autodetección de parámtros al driver Unix OSS.
• 3.9.28: ahora es posible llamar recursivamente a la versión Unix de for_each_file().
• 3.9.28: se añadió la rutina load_datafile_callback().
• 3.9.28: se ha racionalizado el uso de las variables de configuración de sonido, para
que ahora puedan ser compartidas más fácilmente. Por ejemplo sb_freq ha
cambiado a sound_freq.
• 3.9.28: Antti Koskipaa añadió un driver DOS para las tarjetas WSS (Windows
Sound System).
• 3.9.28: el código de flujo de audio ahora es capaz de mezclar múltiples buffers en
uno grande, por lo que seguirá funcionando correctamente incluso si el usuario
provee un buffer más pequeño que el tamaño actual de transferencia de la tarjeta.
Ahora incluso puede reproducir buffers individuales de un byte, ¡siempre y cuando
sea capaz de rellenarlos con la frecuencia necesaria!
• 3.9.28: el código de temporización de Windows es más robusto, por lo que no se
volverá a bloquear cuando se instalen contadores de alta frecuencia.
• 3.9.28: Teijo Hakala añadió soporte de rueda al driver de ratón de Windows.
• 3.9.28: Peter Wang añadió soporte de rueda al driver de ratón de X.
• 3.9.28: Andrew Geers añadió las opciones -ppassword y -nosound al grabber.
• 3.9.28: Keith Gerdes arregló el driver en modo overlay de DirectDraw.
• 3.9.28: Isaac Cruz corrigió el fallo al dibujar en sub bitmaps de superficies
DirectDraw con aceleración por hardware.
• 3.9.28: Peter Wang añadió soporte para modos gráfjcos con bancos del driver
SVGAlib.
• 3.9.28: Peter Wang corrigió algunos problemas con el driver de sonido ESD, y
añadió el driver ALSA.
• 3.9.28: la velocidad de los fundidos de pantalla ahora está controla por
temporizadores para evitar problemas con algunos sistemas (ej: DGA cuando la
profundidad de color es distinta a la ideal) donde pueden ser extremadamente
lentos.
• 3.9.28: se corrigieron varios fallos de desbordamiento que provocaban una
reducción del rendimiento en sistemas Unix muy cargados.
• 3.9.28: ahora el juego demo muestra los créditos de autores.
• 3.9.28: se cambió el sistema de instalación de páginas info. Ahora crea un fichero
dir en el mismo directorio que la página info, en vez de jugar con enlaces
simbólicos, y se usa autoconf para localizar el programa install-info.
• 3.9.28: se añadió el script allegro-lib a la instalacióu Unix, el cual puede ser
ejecutado por ficheros make para obtener la línea de comando adecuada para
compilar programas con Allegro.
• 3.9.28: se añadió salida en formato man a la utilidad makedoc. No funciona muy
bien con apropos debido a la falta del sumario de una línea para cada función, pero
el formateo básico parece estar bien: por favor comunicad cualquier problema que
veáis.
• 3.9.28: parches de George Foot para el manejo de la consola Linux, teclado y
manipulación de ficheros.
• 3.9.28: muchas mejoras de Michael Bukin, en particular mejora del rendimiento en
X, mejor comportamiento del ratón en X y soporte gráfico para DGA.
• 3.9.27: Robert J. Ragno hizo mejoras en el Wingman, PSX y el código de entrada
del mando de gases de joystick.
• 3.9.27: Peter Wang añadió soporte a la rueda de los ratones al código de ratón de
Linux (esto aparece como una nueva variable de estado mouse_z).
• 3.9.27: Patrick Hogan hizo que los flujos de audio de Windows funcionen
correctamente.
• 3.9.27: Sven Sandberg optimizó las rutinas de splines.
• 3.9.27: Tomohiko Sugiura añadió las teclas japonesas KEY_YEN y KEY_YEN2 al
controlador de teclado.
• 3.9.27: Chris Robinson escribió una versión en punto fijo de clip3d_f(), llamada
(¡sorpresa) clip3d().
• 3.9.27: Sven Sandberg mejoró el algoritmo de ordenación del selector de ficheros.
• 3.9.27: Henrik Stokseth mejoró la detección de SO en la versión Windows.
• 3.9.27: Sven Sandberg hizo tablas precalculadas con redondeos más precisos para
las operaciones trigonométricas en punto fijo.
• 3.9.27: George Foot hizo que el driver fbcon reinicie la paleta al salir.
• 3.9.27: mucho código nuevo de Michael Bukin para X: ¡esto funciona ahora
brillantemente!
• 3.9.27: se añadió el path de la biblioteca de funciones X al wrapper de liballeg.a
para Linux. Creo que prefiero la idea de Michael sobre tener un script que devuelva
esta información, así que en el futuro posiblemente cambiemos a este método.
• 3.9.27: corregidos varios fallos tanto en la versión C como i386 del código RLE de
sprites (principalmente relacionado con modos coloreados y formatos hicolor).
• 3.9.27: se añadieron varias correcciones de la 3.12 para que WARNMODE=1
compile limpiamente con gcc 2.95.
• 3.9.27: Knut Pape mejoró el fichero readme de Mingw32.
• 3.9.26: se reescribió el driver de Sidewinder para DOS, tras recibir el pad que me
mandó powerjaw. Todavía no me funciona en modo DOS, pero si bajo Windows,
que es mejor que antes y tan bueno como cualquier otro código que he podido
localizar. Si alguien conoce de algún código que funcione mejor que esto, ¡por favor
comunicádmelo!
• 3.9.26: biestables más flexibles para seleccionar el modo de set_color_conversion().
• 3.9.26: Robert J. Ragno añadió un driver para dispositivos Gravis GrIP.
• 3.9.26: Gorka Olaizola añadió un fichero .spec para paquete RPM de Redhat.
• 3.9.26: Stepan Roh actualizó la traducción al Checo y añadió soporte de múltiples
páginas de códigos a la utilidad textconv, y la función ustrtod() que usa Unicode.
• 3.9.26: se añadió la función ustrdup() a las funciones Unicode.
• 3.9.26: Sven Sandberg optimizó las rutinas matemáticas en punto fijo de gcc para
que colapsen expresiones constantes durante la compilación.
• 3.9.26: Stefan T. Boettner añadió un driver SVGAlib decente para Linux.
• 3.9.26: varios cambios de Vincent Penquerc'h (añadió la opción mezclar ficheros de
datos al grabber, correcciones al GUI, optimizó el cálculo de splines y corrigió la
versión de 24 bits del código C de dibujado).
• 3.9.26: parches para Linux de Michael Bukin que mejoran el driver de sonido OSS,
el manejo de SIGALRM, y el controlador de teclado X.
• 3.9.26: muchos parches para Linux de George Foot (arreglo del controlador de
ratón, biblioteca compartida y script de configuración y varias otras cosas).
• 3.9.25: se corrigió pckeys.c para dejar datos útiles en el array key[] cuando se
emulan las teclas numéricas vs. teclas cursores con numlock.
• 3.9.25: corregido un conjunto de problemag con el modo
SWITCH_BACKGROUND (estúpidamente había olvidado desactivar un montón
de funciones gráficas que podían hacer cosas malas si eran llamadas cuando la
consola de Allegro no estaba activa).
• 3.9.25: se añadieron las funciones pivot_sprite() y pivot_scaled_sprite() (gracias a
Matt Jallo por la sugerencia).
• 3.9.25: se añadió ustrerror() al soporte estándar de funciones Unicode.
• 3.9.25: se corrigió el objeto GUI d_edit_proc() para que maneje el movimiento de
foco shift+tab correctamente.
• 3.9.25: un montón de parches para Linux de George Foot (activación correcta de
fbcon, diferentes tipos de ratón y soporte para configurarlos desde el programa
setup, correcciones al soporte de bibliotecas dinámicas, exedat ya no destruye los
permisos, y posiblemente más cosas que he olvidado).
• 3.9.24: corregidos los fallos del código de sonido y fbcon Linux (esto es más una
versión urgente porque no funcionaban en la versión 3.9.23).
• 3.9.24: James Arthur escribió algo de documentación para las funciones blender
truecolor con estilo Photoshop.
• 3.9.23: Michael Bukin añadió un controlador de sonido OSS al código Linux, y el
principio de un controlador ESD.
• 3.9.23: muchos parches para Linux de George Foot, incluyendo soporte de
biblioteca dinámica.
• 3.9.23: Ole Laursen hizo que las funciones Unicode utolower() y utoupper()
entiendan todo el conjunto de caracteres de 16 bits.
• 3.9.23: Pavlos Touboulidis hizo que file_select() sea capaz de incluir o excluir
ficheros basándose en sus atributos.
• 3.9.23: el objeto GUI d_check_proc() ahora puede imprimir texto a la derecha de la
marca, se selecciona con un valor distinto de cero en el campo d1.
• 3.9.23: cambié de opinión sobre cómo debería funcionar GFX_SAFE, y se quitaron
los parches que emulaban las diferentes profundidades de color. Ahora el driver
GFX_SAFE puede cambiar la profundidad de color si no le gusta lo que se le pide,
y es problema del programador detectar y tratar esto.
• 3.9.23: corregidos los problemas con el renderizado de polígonos usando MMX en
la versión MSVC.
• 3.9.23: se añadió la opción strictwarn del script de configuración, y se corrigió todo
lo indicaba. Los avisos no son muy estrictos: en algún momento me dedicaré a que
compile limpiamente tanto con -W como con -Wall -Werror.
• 3.9.22: corregidas algunas condiciones de carrera potenciales que introduje en mis
correcciones previas al código de temporización de Windows.
• 3.9.22: ahora set_display_switch_callback() es capaz de instalar varias funciones de
enganche, se añadió la rutina remove_display_switch_callback(), y escribí el
programa de ejemplo exswitch.
• 3.9.22: se ajustó la sintaxis del ensamblador en línea de MSVC en un intento de
evitar los conflictos entre las versiones del compilador.
• 3.9.22: un sistema GFX_SAFE más flexible. Además de poder indicar valores
seguros para cada plataforma, ahora puede pasar ceros en la resolución, y si el
controlador activa una profundidad de color no solicitada, graphics.c enganchará
unas rutinas de emulación para que todo funcione bien.
• 3.9.22: George Foot añadió una función al controlador de teclado para convertir
scancodes a ASCII (implementado en DOS, Windows, Linux y X). Esto es
necesario para controlar la combinación alt+tecla correctamente cuando se usan
mapas de teclado inusuales como el Dvorak.
• 3.9.22: parches de George para Linux, mejoran el cambio de consola, soporte de
biblioteca compartida y otras buenas cosas.
• 3.9.22: parche para Windows de Stefan añade muchas cosas geniales, incluyendo
soporte de ventana.
• 3.9.22: Peter Wang hizo funcionar al controlador GGI correctamente.
• 3.9.22: Johan Venter hizo algunas mejoras más a los makefiles de RSXNT y
Mingw32.
• 3.9.22: actualización del makefile de Watcom para permitir forzar manualmente la
detección de la versión 10.6 vs 11.0, en caso de fallo.
• 3.9.21: parche para Windows de Stefan, que añade soporte para el nuevo sistema de
cambio de resolución.
• 3.9.21: más parches para BeOS de Jason Wilkins.
• 3.9.21: Johan Venter corrigió algunos problemas con los makefiles de RSXNT y
Mingw32.
• 3.9.21: ejecuté "configure --enable-asm=no", y corregí todo lo que no funcionaba.
En particular había un fallo en modos de dibujado con relleno, los sprites RLE no
funcionaban, y había olvidado añadir las funciones de sprites RGBA en C. A
aquellos que les gustan estas cosas les interesará saber que los tests consideran el
código C de dibujado un 20% más lento que hline(), 10% más lento que rectfill(),
50% más lento con blitting, y 40% más lento con draw_sprite(), lo cual no está nada
mal. ¡Incluso es más rápido dibujando sprites translúcidos o coloreados! Así que
habrá que comprobar eso.
• 3.9.21: muchos nuevos parches para Linux de George Foot.
• 3.9.21: se añadió soporte VBE/AF para Linux.
• 3.9.21: se terminó el driver fbcon para Linux.
• 3.9.21: se hizo que el cambio de consola bajo Linux funcione de forma más
completa, con ayuda de las funciones de dispsw.c. El modo en segundo plano ahora
debería funcionar, pero no está probado.
• 3.9.21: Carsten Schmidt añadió un driver GGI para Linux (está algo retrasado y no
funciona, pero es un buen comienzo en caso de que alguien quiera trabajar en él).
• 3.9.21: se mejoró el sistema de configuración y compilado bajo Unix. Se movieron
más cosas a makefile.lst, por lo que ya no hay listas de ficheros en ninguna otra
parte. Ahora el proceso sabe cómo crear las utilidades de ficheros de datos, y
convertir la documentación (esto puede causar problemas en sistemas que no
dispongan de makeinfo: estaría bien que alguien que conozca autoconf mejore esto).
Se hicieron los drivers VGA de Linux (vga y modo-x) configurables.
• 3.9.21: se añadió la secuencia ctrl+alt+end para abortar al controlador de teclado de
Linux.
• 3.9.21: cambios en la estructura de directorios: se movió ufile.c al directorio misc,
para que BeOS pueda compartirlo. Se movieron varios scripts de ayuda al directorio
misc, incluyendo a cmplog.pl, que compara dos ficheros log de rendimiento
generados por test.exe.
• 3.9.21: el controlador de ratón PS2 para Linux ahora detecta el botón central. Se
añadió también un factor de escalado para hacerlo más sensible en modos SVGA.
• 3.9.20: se comenzó a escribir un driver para fbcon bajo Linux. Funciona, pero
todavía no es capaz de cambiar la resolución.
• 3.9.20: parches de Stefan para Windows, añaden control de joystick y los
comienzos de un driver para modos de vídeo en ventana.
• 3.9.20: se movieron todos los listados de ficheros (incluso los específicos de cada
plataforma) a makefile.lst, para evitar cualquier duplicación y tener un lugar
centralizado que mencione todos los ficheros que usemos.
• 3.9.20: se eliminó la función install_lost_bitmap_callback() en favor de otra más
genérica: set_display_switch_mode(). Se actualizó el código Windows para usar
estas nuevas rutinas.
• 3.9.20: se introdujo un parche de Michael Bukin (añade soporte de ratón).
• 3.9.20: Vincent Penquerc'h optimizó el código de blitting de gráficos de 256 colores
a truecolor para evitar repetir conversiones de la paleta de colores.
• 3.9.20: James Hyman añadió soporte de cadenas entrecomilladas a
get_config_argv().
• 3.9.20: Peter Cech optimizó las rutinas de sprites con canal alfa. Shawn las optimizó
un poco más al expandirlas en versiones especializadas para las profundidades de
color más comunes.
• 3.9.20: Richard Davies hizo algunas mejoras al driver de pad PSX.
• 3.9.20: se añadió un parámetro de driver de sistema a allegro.cfg, y rutinas de
enganche para que los sistemas Unix busquen los datos de configuración en /etc/ y
~/.
• 3.9.20: se movió la emulación Posix de findfirst() a libc.c, quitándola de autoconf y
compilaciones específicas BeOS.
• 3.9.20: más parches para BeOS de Jason Wilkins. ¡Las rutinas gráficas ya funcionan
ahí!
• 3.9.20: se mejoró el driver VBE/AF para que sepa que las líneas verticales se
pueden implementar con un rectfill. Esto permite dibujar líneas verticales con
patrón de relleno, y dibujar las líneas en hardware que no soporte esta rutina
acelerada por hardware.
• 3.9.20: George Foot realizó mucho trabajo para que la versión Linux modo consola
funcione de modo realmente convincente.
• 3.9.20: las listas de controladores de sonido de Windows ahora son generadas
dinámicamente en base a los dispositivos existentes, para que se pueda seleccionar
cuál usar.
• 3.9.19: escribí la primera partelde la Guía del Hacker de Allegro, mi
(probablemente futil :-) intento de documentar al menos las partes más delicadas del
código de Allegro.
• 3.9.19: finalmente documenté las funciones Unicode.
• 3.9.19: más parches para BeOS de Jason Wilkins.
• 3.9.19: Michael Bukin realizó algunos cambios más al código X (los
temporizadores ahora estan implementados), y añadió una implementación
completa (?) en C del código de dibujado. Máquinas no-Intel, ¡aquí venimos! Si
define ALLEGRO_USE_C antes de compilar la biblioteca para djgpp, podrá probar
una versión en C puro de test.exe, el juego demo, etc.
• 3.9.19: se añadió el script findtext.sh, que escanea el código fuente y crea una lista
de todas las cadenas disponibles para traducir. También puede comparar esta lista
contra un fichero de traducción ya existente, para ver si se han añadido nuevos
mensajes.
• 3.9.19: Stepan Roh actualizó el mapa de teclado checo para que soporte Unicode,
añadió a keyconf soporte para usar fuentes no estandar, y añadió los carácteres Latin
Extended-A (de U+0100 a U+017F) a la fuente por defecto.
• 3.9.19: Grzegorz Adam Hankiewicz actualizó la traducción al español con cadenas
en formato UTF-8 (propiamente acentuadas). Se ordenó la fuente del programa
setup a Latin-1 para que sea mostrada correctamente. Se corrigió el fallo de dat2s,
que convertía incorrectamente la fuente resultante de múltiples rangos.
• 3.9.19: Chris La Mantia realizó cambios cosméticos al objeto GUI d_slider_proc().
• 3.9.19: Richard Davies añadió soporte para pads de la N64.
• 3.9.19: añadí keyboard_ucallback() (me olvidé de esta al añadir el soporte Unicode).
• 3.9.19: se hicieron algunos cambios a setup.c para que pueda ser incluído dentro de
otros programas (gracias a Grzegorz Adam Hankiewicz por la sugerencia).
• 3.9.18: se añadió soporte para imágenes RGBA de 32 bits. Ahora puede leer
imágenes TGA con canal alpha desde el grabber, o puede importar una imagen
normal y luego el canal alpha desde un bitmap en escala de grises. Puede salvar
estos canales alpha como parte de un fichero de datos, llamar la función makeacol(r,
g, b, a), y más importante aún, llamar a set_alpha_blender() y luego
draw_trans_sprite() para mostrarlos. Compruebe exalpha.c. Hay bastantes
posibilidades de optimizar las versiones de 15, 16 y 24 bits de _blender_alpha*(), en
caso de que alguien quiera mejorar esto. Creo que sería beneficioso escribir
versiones específicas para cada profundidad de color y quedarnos con la versión
genérica actual como versión de seguridad.
• 3.9.18: más parches Unix de Michael Bukin. Ahora todo compila sin problemas, a
pesar de que todavía no haga nada interesante.
• 3.9.18: Jason Wilkins contribuyó los comienzos de un port para BeOS (todavía no
es funcional, pero compila).
• 3.9.18: Revin Guillen añadió la función position_dialog().
• 3.9.18: mejoras de portabilidad: se cambió el makefile para que sea generado, el
cual normalmente incluye makefile.all, pero puede ser completamente reemplazado
por autoconf, y se movieron las emulaciones de las funciones libc a código fuente
compartido.
• 3.9.18: numerosas correcciones.
• 3.9.17: Burton Radons cambió las funciones truecolor de pixel blending para que
usen una función callback en vez de la tabla previa. Esto puede romper la
compatibilidad con código antiguo, pero debería resultar eternamente compatible y
el nuevo método es mucho más flexible. También añadió un conjunto completo de
funciones blender, incluyendo modos Photoshop como quemar, diferencia,
luminosidad, etc.
• 3.9.17: Richard Davies añadió soporte para joypads PSX.
• 3.9.17: corregido el fallo de dat2s al manejar imágenes truecolor.
• 3.9.17: Jason Wilkins mejoró las rutinas matemáticas de cuaterniones, y añadió algo
de documentación sobre ellos.
• 3.9.17: Neil Townsend añadió parámetros callback a los controladores de
temporización.
• 3.9.17: Gunter Ladwig añadió emulación del tercer botón del ratón, que puede ser
activada mediante el fichero de configuración (por defecto está activado si tiene un
ratón de dos botones.
• 3.9.16: se aplicaron algunos parches de Michael Bukin, que añaden un sistema base
de compilación Unix. Sin embargo todavía no funciona :-)
• 3.9.16: se incluyó nuevo código de Stefan. Ahora funcionan más cosas geniales de
la versión Windows, ej: aceleración por hardware, triple buffering, sonido...
• 3.9.16: se añadió un ejemplo sobre cómo escribir un salvapantallas para Windows
usando Allegro. Si alguien sabe cómo hacer que aparezca un nombre representativo
en el diálogo de selección de Windows, ¡por favor dígamelo! (he creado la tabla de
cadenas según MSDN es necesaria, pero no funciona).
• 3.9.16: Andy Goth añadió el objeto de diálogo d_text_list_proc(), que le permite
alterar la selección tecleando los primeros caracteres de una entrada de la lista.
• 3.9.16: Ole Laursen actualizó la traducción danesa de los mensajes.
• 3.9.16: Calvin French añadió el parámetro -w (siempre actualizar) al programa
dat.exe.
• 3.9.16: Joerg Rueppel añadió al dat.exe una comparación de caracteres más flexible
para los nombres de los objetos.
• 3.9.16: se añadieron los biestables GFX_HW_SYS_TO_VRAM_BLIT y
GFX_HW_SYS_TO_VRAM_BLIT_MASKED, y funciones de blitting más
flexibles a la vtable.
• 3.9.16: se añadieron los métodos lock_voice() y unlock_voice() al driver de sonido
digital, para implementar los flujos de audio bajo Windows.
• 3.9.16: ahora _handle_timer_tick() devuelve el espacio deseado hasta la siguiente
interrupción.
• 3.9.15: Michael Rickmann añadió un port a Mingw32. Este funciona actualmente
como la versión RSXNT, usando MSVC para construir la DLL, pero se convertirá
en un port completo cuando el núcleo del código Windows se estabilice un poco.
• 3.9.15: Vincent Penquerc'h añadió la bandera D_DIRTY a los objetos GUI, y yo lo
extendí con un nuevo código de retorno D_REDRAWME para los controladores.
• 3.9.15: se cambió la sintaxis de la función callback de create_color_table(). Esto
rompe la API, pero es la única forma de hacer que funcione con las diferentes
convenciones de llamada de los compiladores.
• 3.9.15: se añadieron a la estructura vtable ganchos para crear sub bitmaps (para que
el bitmap pueda saber cuándo es clonado).
• 3.9.15: "make install" es ahora un comando separado, no ejecutado
automáticamente. Esto significa que debe ejecutar "make" y "make install" como
dos operaciones separadas, o si quiere las tres versiones de la biblioteca, "make all"
y entonces "make installall".
• 3.9.15: se añadió la macro END_OF_MAIN(), la cual hace funcionar la magia de
WinMain() correctamente en cualquier combinación de código C y C++.
• 3.9.15: Olly Betts modificó el makefile de djgpp para soportar compilación cruzada
desde una máquina Linux.
• 3.9.15: Andy Goth añadió un modo VGA modificado de 256x256.
• 3.9.15: actualización mayor de la documentación (de ahora en adelante iré
añadiendo un número de versión a cada comentario de este fichero).
• Se incluyó el nuevo código de Stefan. La versión Windows se acerca cada vez más
a estar completa, incluyendo soporte para ratón y bitmaps de vídeo, aunque el
código de ratón todavía no me funciona correctamente.
• Se reescribió fix_filename_path() para evitar llamar a _fixpath(). La nueva versión
es más portable, aunque cosas como leer el directorio actual a través de múltiples
unidades necesitan ajustes para funcionar con diferentes compiladores.
• Corregidas varias cosas que impedían funcionar la versión Watcom. Ahora se
ejecuta todo sin problemas, ¡incluyendo joyas como exdodgy y la opción shell edit
del grabber! Según test.exe, gcc 2.8.1 es un 10% más rápido que Watcom 10.6 para
la mayoría de las cosas, aunque por alguna razón textout() es el doble de rápido en
la versión Watcom.
• Se corrigieron varias cosas para que funcione la versión RSXNT. Ahora todos los
tests y ejemplos compilan con RSXNT, y funcionan de forma idéntica a los
originales de MSVC.
• Se añadieron las rutinas matemáticas de cuaterniones de Jason Wilkins.
• Andy Goth añadió un soporte más flexible a la configuración de gfx_card.
• Se añadió la función masked_stretch_blit() (cambio trivial, el código podía hacerlo,
pero faltaba el punto de entrada de la API.
• Se añadieron las rutinas Windows GDI por Marian Dvorsky.
• Se añadió un poll de DMA al driver de la Soundscape, para asegurarnos de que
nunca perderá la sincronización durante la transferencia.
• Incluí varias cosas que han estado cogiendo polvo en mi disco duro durante décadas
(traducciones suecas y noruegas, varios parches de Michael Bukin, nuevo código de
generación de paletas por Michal Mertl, y correcciones al driver Soundscape por
Andreas Kluge).
• Grabber ahora reconoce y manipula fuentes Unicode.
• Ahora se pasa atexit() como parámetro a install_allegro(), para evitar problemas con
la desinicialización de la DLL.
• Se hizo que el reproductor FLIC active las variables "sucias" cuando se limpia el
bitmap en un punto de comienzo/loop (esto hacía que a veces no se limpiase el
contenido previo de la pantalla).
• Se corrigieron varios fallos en el grabber.
• Se cambiaron las utilidades de ficheros de datos para que enlacen con datedit y las
rutinas plugin como una librería. Esto le hace la vida más fácil a terceros que
quieran usar esas rutinas (duplicar el enlazado de plugins no es muy divertido).
• Se reemplazaron las referencias errno con el puntero allegro_errno, para evitar
problemas con múltiples versiones al enlazar con la DLL. ¡La versión MSVC de dat
ahora funciona perfectamente!
• Se añadió el driver system_none para herramientas de línea de comando o otra
situaciones neutrales.
• Hice una nueva animación para la demo. ¡Mi primer render con Max!
• Se incluyeron parches para Windows de Stefan. ¡Whoah! Esto es genial. Funciona
(más o menos :-) en dos plataformas. Ahora puedo morir feliz...
• El selector de ficheros ahora se ajusta a plataformas sin listado de directorio (ej:
Unix).
• Se añadió la paleta global default_palette (la normal de la BIOS IBM), y
set_gfx_mode() la selecciona.
• Se modificó el driver DIGMID para evitar usar enteros de 64 bits o coma flotante
dentro de la interrupción.
• Se añadieron las rutinas de depuración ASSERT() y TRACE(), y montones de
aserciones a lo largo del código de la biblioteca.
• El formato de pixel por defecto en modos truecolor antes de activar el modo de
vídeo es BGR en vez de RGB. Esto debería mostrar los fallos en el soporte BGR y
capturar los errores donde la gente esté cargando gráficos antes de ajustar el modo
de vídeo.
• Corregido el fallo de detección de desbordamiento en fmul().
• Reescribí gpro.c y sw.c para evitar usar ensamblador en línea. El código SW es muy
feo (traducción literal de la rutina en ensamblador), pero estoy dispuesto a mejorarlo
si recibo respuesta de alguien que lo pruebe. Si tiene un Gamepad Pro o un
Sidewinder, y era capaz de usarlo con Allegro 3.11, estoy _realmente_ interesado en
oír si esta nueva versión funciona o no...
• Numerosos cambios para hacer los programas de soporte más portables.
• Se añadió la función get_executable_name().
• El fichero sound.cfg ya no está soportado. Use allegro.cfg en su lugar.
• Se añadieron versiones de las funciones inline _putpixel() y _getpixel() para todas
las profundidades de color.
• La función check_cpu() ahora es llamada automáticamente por allegro_init().
• Se añadieron objetos bitmap de sistema, que existen en la memoria ram pero son
accedidos de forma similar a las superficies en memoria de vídeo (esto puede
mejorar la aceleración por hardware en algunas plataformas).
• Se añadieron las funciones enable_triple_buffer(), timer_can_simulate_retrace(), y
timer_is_using_retrace(). Esto permite a los programas manejar correctamente la
interrelación entre triple buffering, el modo de sincronización con el retrazo, y el
SO actual, sin tener que incluir código específico del DOS.
• Las rutinas GUI ahora llaman apropiadamente las funciones de polling y hacen
acquire/release de la pantalla cuando es apropiado.
• Corregido un verdadero error show-stopping que provocaba cuelgues del VBE/AF
en algunas máquinas (llamar funciones del driver con el selector de memoria
segmentada %es).
• Se añadió la función allegro_message().
• Se añadieron rutinas tontas de cambio de banco que pueden emular acceso lineal a
una pantalla en modo-X, aunque de forma lenta. El único resultado práctico de esto
es que las rutinas de polígonos ahora funcionan en modo-X, pero ayuda a hacer las
cosas más robustas en general (si una rutina no sabe nada sobre el modo-X, ahora se
ejecutará más lentamente de lo normal, en vez de no funcionar en absoluto).
• Los drivers SB, Adlib, y joystick estándar tienen una instancia propia para cada
variante de hardware, en vez de un solo driver que pretendía existir bajo múltiples
códigos de identificación.
• Se reescribió el polling de joystick para evitar código ensamblador en línea.
• Se convirtieron los ficheros de traducción al formato UTF-8. Estos pueden usar
ahora cualquier carácter Unicode, por lo que las vocales acentuadas, etc, pueden ser
usadas sin problemas.
• Los scancodes se han convertido de un formato dependiente del hardware a una
codificación abstracta específica de Allegro. Esto simplifica mucho el código y
evita problemas cuando dos teclas diferentes generan el mismo scancode.
• Se añadió la función genérica find_allegro_resource(), la cual elimina un montón de
código duplicado de config.c, digmid.c, y pckeys.c.
• El módulo de temporización ahora se auto instala cuando alguien intenta usarlo.
• Las funciones de teclado ahora pueden alterar la velocidad de repetición.
• Port a Watcom.
• Se añadió la ID especial del driver GFX_SAFE.
• Ahora se usa VDS para detectar win95 incluso cuando se está ocultando.
• Se añadió fixver.sh para parchear números de versiones y fechas al lanzar una nueva
versión (requiere bash, fileutils, shutils, etc, para ejecutarse bajo DOS).
• Se añadió zipup.sh para crear ficheros zip y diff de distribución, el cual limpia
automáticamente el árbol de directorios (ej: pregenera los ficheros de dependencia
para todos los compiladores soportados).
• Se añadieron funciones poll de entrada.
• Restructuración importante del código, se añadieron drivers de sistema, nuevo
código para tratar la entrada del usuario, temporizadores, conversión de scancodes
de teclado, acceso a ficheros, etc.
• Se añadió soporte completo de textos Unicode, incluyendo funciones para
manipular cadenas, un nuevo formato para las fuentes, la utilidad textconv, un
nuevo mensaje GUI MSG_UCHAR, y una función ureadkey().
• Se añadieron fuentes monocromas de tamaño variable, reemplazando el antiguo
formato fijo 8x8. Como resultado, el biestable GFX_HW_TEXTOUT_FIXED ha
sido renombrado a GFX_HW_GLYPH.
• Nuevo sistema para acceder a la memoria de vídeo, usando bmp_select(),
bmp_write*(), y bmp_unwrite_line(). Esto es equivalente a las funciones farptr de
djgpp, pero portables a diferentes plataformas.
• Reorganización drástica de la estructura de directorios, el sistema de ficheros make,
etc.
• Se mejoró la utilidad makedoc para simplificar la tarea de añadir enlaces y
direcciones de email a la documentación.
• Se añadió un parche para que el código VESA funcione con drivers Trio64 S3
estropeados.
• Se quitó el código de detección del procesador 386DX vs. 386SX (a veces cascaba).

Cambios de 3.11 a 3.12 (Agosto 1999)


• Se corrigieron algunas incompatibilidades con gcc 2.95. Esta versión es en el resto
idéntica a la versión 3.11.

Cambios de 3.1 a 3.11 (Febrero 1999)


• Se limpiaron algunos sitios donde la memoria no era liberada durante el cierre del
sistema. Un detalle cosmético, ya que el SO la liberará por nosotros, pero es bueno
hacer todas estas cosas bien.
• Alessandro Monopoli tradujo al Italiano los mensajes de sistema.
• Henrik Stokseth añadió código para distinguir entre win95 y win98.
• Se ha quitado a Creative Labs del fichero THANKS, debido a su negativa de
proporcionar documentación sobre la tarjeta SB Live.
• Se cambió el nombre de la biblioteca de funciones. Después de años pensando que
Allegro era una palabra sin un sentido particular, descubrí que de hecho es un
acrónimo recursivo de "Allegro Low Level Game Routines".
• Se estableción una nueva lista de correo (conductors@canvaslink.com) para las
personas que trabajan en Allegro. Por favor, mande sus contribuciones de código a
esta lista en vez de a mí directamente (Shawn Hargreaves), porque esto permitirá
que el desarrollo de Allegro continúe aun cuando no esté por aquí o esté ocupado
con otra cosa en el momento.
• Andreas Kluge escribió un controlador para las tarjetas Ensoniq Soundscape.
• Más localización: traducción de los mensajes de sistema al sueco por Sven
Sandberg, Anton Ragnarsson y Erik Sandberg, traducción de los mensajes de
sistema al finlandés por Antti Haapala, y traducción de los mensajes de sistema y
mapa de teclado rusos por Dmitriy Kazimirow.
• La función midi_out() ahora actualiza correctamente el estado de los controladores
de pan/volumen/bend.
• Kester Maddock añadió un controlador para el joystick Wingman Warrior.
• Se solucionaron algunos problemas con los controladores del Sidewinder, Gamepad
Pro y joypad SNES.
• Se cambió el controlador de la SB16 para que use un modo de salida de 16 bits con
signo, en lugar del antiguo formato sin signo. Esperemos que esto mejore la
compatibilidad con las copias baratas de hardware.
• Se añadió el parámetro de entorno WARNMODE al makefile. Los desarrolladores
de Allegro deberían usarlo para recibir mensajes de aviso más estrictos, pero será
desactivado por defecto para que las versiones de distribución sean más permisivas
respecto a diferentes versiones de compilador/biblioteca libc.
• Solucionado el problema al leer las posiciones arriba e izquierda en joysticks
digitales.
• Solucionado (creo, todavía espero información detallada sobre esto :-) el problema
con los temporizadores corriendo muy rápido en algunas placas madre.
• Solucionado el fallo estúpido cuando get_align_matrix() no se preocupaba de poner
ceros en el vector de translación.
• Solucionado el fallo de los sprites rotados que aparecían invertidos en modo-X y
modos hi/truecolor.
• Solucionado el fallo de la utilidad dat que truncaba los nombres largos al formato
8.3.
• Se renombró el fichero ChangeLog a CHANGES, para evitar problemas en sistemas
8.3.
• Varias otras correcciones menores.

Cambios de 3.0 a 3.1 (Enero 1999)


• Cambios entre la beta 3.1 y versión final: varios fallos corregidos, Antoine Mathys
añadió un mapa de teclado suizo, Thomas Wolf añadió una traducción alemana del
sistema de mensajes.
• Cambios entre las versiones 3.1 alpha y beta: varios fallos corregidos, las rutinas
FLIC ahora pueden leer de ficheros de datos, se incluyeron las optimizaciones para
rotar sprites por Ivan Baldo.
• Peter Cech añadió soporte para cambiar mediante una combinación de teclas entre
el mapa de teclado americano y el mapa de teclado personalizado.
• Neil Townsend mejoró la precisión de las rutinas de temporización.
• Se añadió el programa de ejemplo exlights, que enseña un modo para hacer efectos
de luz coloreada en modo hicolor (y también porque hace que el número total de
ejemplos sea un bonito número redondo :-)
• Se añadió el programa test afinfo, que hace lo mismo que vesainfo pero para los
controladores VBE/AF.
• Michael Bukin hizo muchos parches de portabilidad y corrigió algunos fallos,
incluyendo algunas mejoras al reproductor de ficheros FLIC y un sistema de manejo
de ficheros más racional.
• Se quitaron los controladores de chips específicos de SVGA de la distribución
principal de la biblioteca. En su lugar, estos controladores estarán disponibles tanto
como un paquete adicional como parte del proyecto FreeBE/AF.
• Se añadió el soporte de extensión FreeBE/AF al controlador VBE/AF de Allegro
(acceso farptr a la memoria de vídeo, y las exportaciones libc y pmode necesarias
para futura compatibilidad con los controladores SciTech Nucleus).
• Se corrigió un fallo con la función vline translúcida y dibujo con patrón en las
profundidades de color de 15 bits.
• Se corrigió un puntero NULL en las rutinas de configuración.
• Se corrigió un error en el órden de proceso que causaba que los datos se perdiesen al
llamar a set_config_file() con el mismo nombre de fichero que el fichero de
configuración actual.
• Stepan Roh añadió una traducción de los mensajes de sistema en Checoslovaco.
• Ole Laursen añadió una traducción de los mensajes de sistema en Danés.
• Grzegorz Ludorowski hizo una nueva animación introductoria para la demo.
• Calin Andrian añadió rutinas de conrtrol de rendimiento de polígonos 3d al
programa test.exe.
• Peter Cech añadió al grabber soporte para la fuente 8x8 de la BIOS.
• Stepan Roh añadió un mapa de teclado checoslovaco.
• Se renombró el fichero de traducción español de SP a ES.
• Calin Andrian añadió un conjunto completo de rutinas de renderización de
polígonos truecolor, con soporte para optimizaciones MMX y 3DNow! y un nuevo
modo de dibujo, junto con una nueva función de recorte de polígonos. Un cambio
menor es que ahora el modo POLYTYPE_FLAT está implementado con llamadas a
hline(), por lo que responderá al ajuste actual de drawing_mode().
• Se cambiaron los números ID de controladores de gráficos/sonido/joysticks a una
lista con cadenas descriptivas de 4 caracteres, para que sea más legible y flexible. Se
añadrieron funciones de configuración para leer/escribir datos en este formato. Los
datos de configuración de sonido son compatibles con los viejos, pero tendrá que
actualizar manualmente cualquier número de controlador gráfico o de joystick que
esté almacenado en su fichero de configuración.
• Michael Bukin contribuyó _un montón_ de parches para mejorar la portabilidad y
robustez de prácticamente toda la biblioteca. El único cambio visible externamente
es que las macros usadas para declarar listas de controladores han sido rediseñadas a
una sintáxis más portable, a pesar de que la antigua sigue estando disponible como
una macro de compatibilidad.
• Burton Radons hizo más optimizaciones de la función de fundido truecolor de
pixels.
• Martijn Versteegh añadió un mecanismo de enganche para extender el sistema de
configuración, que puede ser usado para proveer información extendida sobre el
estado del sistema o para rutinas personalizadas para paquetes añadidos.
• Se rediseñaron las utilidades grabber y dat para soportar módulos "plugin" de
código fuente, que pueden ser usados para extender el sistema con tipos de objetos
adicionales, rutinas importar/exportar, y comandos de menú.
• Ivan Baldo añadió una opción de difuminado a las rutinas de conversión de color de
15/16 bits.
• Kerry High añadió un controlador para el pad de la SNES.
• Se añadió un parámetro a los objetos GUI d_text_proc() y d_ctext_proc(), para que
usen una fuente personalizada apuntada por el campo dp2.
• Michael Tanczos solucionó algunos fallos en el reproductor de ficheros FLIC.
• Cloud Wu optimizó las funciones de fundido de pixels truecolor.
• Paul Pinault añadió una traducción francesa al sistema de mensajes de error.
• Grzegorz Adam Hankiewicz añadió una traducción española al sistema de mensajes
de error, y añadió un nuevo (pero no documentado :-) parámetro de línea de
comando al juego demo.
• Se solucionaron los clicks en la mezcla interpolada de samples.
• Se solucionó un fallo en el que position_mouse() no actualizaba la variable
mouse_pos.
• Se solucionó un fallo de scroll horizontal en modo-X mientras el temporizador que
simula el retrazo estaba activo.
• Se añadió un fichero language.dat, que puede ser usado para proveer versiones
traducidas de textos de sistema (ej: mensajes de error), de un modo similar al
existente keyboard.dat. Si quiere usar este mecanismo para su propio código,
sustuya sus cadenas constantes con llamadas a get_config_text("texto"). Esto
permitirá que sean traducidas incluyendo una línea al estilo "texto=textotraducido"
en la sección relevante de language.dat.
• Se añadió un campo de nombre ASCII a los ficheros de mapas de teclado, para
hacer el programa setup algo más amistoso.
• Se incrementó el número máximo de canales de sonido de 32 a 64.
• Se modificó el cargador de parches DIGMID para soportar samples de 16 bits, para
evitar la reducción automática a 8 bits.
• Se añadió una opción de interpolación al mezclador de sonido (quality=2).
• Salvador Eduardo Tropea añadió soporte real de 16 bits al mezclador de sonido
(quality=1).
• Lee Killough añadió una rutina de bajo nivel al controlador de teclado.
• Se quitó el código en coma flotante del controlador DIGMID para evitar potenciales
sobrecargas de la pila de la FPU.
• Jim Flynn quitó los cálculos en coma flotante del controlador MIDI AWE32 (éstos
aveces podían producir sobrecargas de pila).
• Salvador Eduardo Tropea mejoró el sustema de ficheros de datos para evitar enlazar
código no usado.
• Romano Signorelli contribuyó la función Bresenham de dibuado de arcos.
• Thomas Wolf corrigió unos errores del mapa de teclado Alemán.
• Grzegorz Adam Hankiewicz mejoró el ejemplo excolmap.
• Sven Sandberg optimizó las rutinas trigonométricas de punto fijo.
• Solucionados algunos fallos estúpidos del código de joystick.
• Se añadió la opción "compress" al makefile, basada en una sugerencia de Grzegorz
Adam Hankiewicz.
• Se añadieron funciones vacías aquire/release bitmap a allegro.h para mantener la
compatibilidad con la versión Windows.
• Se añadieron referencias cruzadas al formato Info de la documentación.
• Martin Fuller arregló un fallo muy obscuro en la lectura de ficheros .bmp
comprimidos.
• El controlador de señal de salida de emergencia ahora recupera correctamente el
controlador previo, en vez de resetear la acción por defecto.
• Sven Sandberg optimizó la función create_light_table().
• George Foot corrigió un fallo cuando la rutina get_mouse_mickeys() era llamada
siendo ambos parámetros la misma variable.
• Se cambió el término de licencia de "swapware" a "giftware". Mire la web de
Allegro para leer una explicación de este cambio.
• Se añadieron aun más operadores (esta vez de tipo long y double) a la clase fija.
• Marius Fodor añadió soporte para el Sidewinder y el Gravis Gamepad Pro. ¡Lo
siento por haber tardado tanto en incluir este código!
• Stefan Schimanski optimizó la rutina de blit invertido (para imágenes que se
sobreescriben)
• Se añadió a las rutinas GUI el movimiento hacia atrás del foco con las teclas
shift+tab.
• Grzegorz Adam Hankiewicz añadió un nuevo ejemplo que enseña cómo crear y usar
una tabla de mapeado de color propia.
• Se reescribió el sistema joystick (mejor API y nueva estructura driver).
• Modificada la clase fija para que funcione bien con gcc 2.8.0.
• Añadido el fichero help.txt "cómo conseguir soporte técnico".
• La variable midi_pos ahora es negada, en vez de ajustada a -1, al final del fichero
MIDI. Esto puede usarse para medir el tamaño del fichero.
• Se añadió un gancho de render a la estructura font, para uso de los addons de texto.
• Se mejoró la rutina VBE/AF de salida de texto.
• Corregido el error en el cual el driver VBE/AF interpretaba colores de cursores
hardware.
• Pedro Cardoso contribuyó un modo trucado VGA 80x80.
• El driver VBE/AF ahora soporta tanto drivers tontos con framebuffer como drivers
acelerados.
• Se añadió más soporte de aceleración al driver VBE/AF (cursores hardware, líneas,
líneas verticales, triángulos, salida de texto de ancho fijo, y blits
opacos/enmascarados desde memoria de sistema a la pantalla).
• Se añadió la función scare_mouse(), basada en ideas de Martijn Versteegh.
• Grabber ahora almacena el estado del diálogo "grab from grid" en allegro.cfg.
• Sven Sandberg solucionó un problema con los anchos de save_bitmap() que eran
redondeados hacia arriba.
• La bandera _timer_installed es ahora globalmente visible.
• Ove Kaaven añadió soporte de framebuffer lineal al driver nativo mach64.
• Erik Sandberg optimizó las funciones draw_sprite() y draw_trans_sprite() de 8 bits.
• Michal Mertl solucionó un agujero de memoria en la función
generate_optimized_palette()
• Se añadió la definición ALLEGRO_DATE a allegro.h.
• Michael Bukin optimizó la rutina de dibujado de líneas y solucionó el problema de
las funciones fadd()/fsub() inline en ensamblador.
• Solucionados los problemas potenciales causados por la diferencia de tiempo entre
las variables de estado del ratón y el puntero que estaba siendo redibujado.
• Michal Mertl optimizó el código de área de recorte para las líneas, rectángulos y
círculos.
• Maiolino Carmelo contribuyó un mapa de teclado Italiano.
• Solucionados los bloqueos causados por las funciones de LED del teclado en
algunas plataformas/hardware.
• Se añadieron las funciones nuevas create_video_bitmap() y show_video_bitmap().
• Se añadió una opción para medir la velocidad en el programa test.
• El controlador de teclado ahora actualiza correctamente el estado de las teclas
control y alt en la BIOS cuando se cierra.
• Solucionado un problema que evitaba que el driver DIGMID leyese patches
almacenados en ficheros de datos añadidos a ficheros ejecutables.
• Cambiada la prioridad por defecto de los samples de 255 a 128.
• Solucionados algunos problemas con tamaños virtuales de pantalla en el driver
VBE/AF.
• Añadidos dos ejemplos nuevos.
• El driver VBE/AF ahora tiene soporte total para dibujado acelerado por hardware.
• Añadido soporte VBE 3.0, incluyendo las nuevas rutinas de triple buffer.
• Se escribió una rutina para seleccionar la entrada de sonido (micrófono, línea o
CD).
• Se añadió soporte decente para samples estéreo. Esto requería un parámetro extra a
la función play_audio_stren(), por lo que tendrás que cambiar todos los programas
que usen esto. ¡Lo siento mucho por romper tu código antiguo!
• Solucionados los fallos de autodetección de la SB16 y la grabación de samples a 16
bits.
• Añadido soporte a la interfaz de driver bruto SB MIDI.
• Se escribió un nuevo programa de test que demuestra las características de entrada
de audio.
• Ove Kaaven añadió soporte de entrada de audio (samples) y MIDI.
• La función pack_fopen() ahora entiende los ficheros de datos anidados como
estructuras de directorio, usando nombres de fichero como
"graphics.dat#level1/sprites/zdurgle".
• Charles Mac Donald me enseñó cómo activar el modo VGA 160x120, y
resoluciones de modo-X 400x* de más confianza.
• Guilherme Silveira y Theuzifan Sumachingun modificaron ambos
independientemente el seleccionador de ficheros para que enseñase sólo letras de
unidades válidas.
• Carsten Sorensen añadió un driver para la tarjeta de sonido ESS AudioDrive.
• Przemek Podsiadly añadió versiones hicolor de las rutinas de polígonos 3d.
• Ove Kaaven añadió soporte truecolor al driver nativo ATI mach64.
• Patrick Hogan añadió una función draw_goraud_sprite().
• Ben Chauveau añadió el driver para tarjetas Tseng ET6000.
• Marco Campinoti añadió soporte truecolor al driver nativo Tseng ET4000.
• Marco Marmulla añadió soporte de 16 bits a la rutina load_voc().
• Se añadieron mapas de teclado Daneses, Suecos y Noruegos.
• Se añadió un gancho a las funciones GUI para escalar u offsetting la posición del
ratón.
• Se solucionó un fallo que causaba un bloqueo cuando llamabas set_leds(-1).
• Michael Bevin optimizó la función create_trans_table().
• Ahora es posible enseñar un puntero de ratón sin tener que instalar el controlador de
ratón.
• Se añadió la función create_sample().
• Se hizo que las funciones de fundido _blender_map y las banderas
_mouse_installed, _keyboard_installed, y _sound_installed sean visibles
globalmente.
• Se añadió un modo joystick de 8 botones.
• Chris La Mantia solucionó un problema visual menor de d_icon_proc().
• Se añadió el formato de texto enriquecido (.rtf) a la documentación.
• Se añadieron operadores de incremento/decremento postfix a la clase fija de C++, y
el operador de negación unary es ahora correcto.

Cambios de 3.0 beta a final (Diciembre


1997)
• La utilidad pat2dat ahora puede importar instrumentos de ficheros SoundFont de la
AWE32.
• Optimizado el cargador de patches DIGMID y corregidos varios fallos.
• Ove Kaaven corrigió el driver de la ATI Mach64.
• El fichero de configuración ahora puede mencionar varios drivers de video posibles,
usando líneas de la forma gfx_driver=x, gfx_driver2=x, etc.
• Mejoradas las funciones de ayuda del controlador nativo SVGA, haciendo más fácil
el añadir soporte truecolor a los drivers de nivel de registro.
• Hacer doble click en un objeto de fuente en el grabber the permite ahora ver los
carácteres extendidos así como los ASCII normales.
• Markus Oberhumer corrigió el problema potencial de la Video-7 del código de
inicialización.
• Markus Oberhumer, Bitland y Sormuras me enviaron las tablas de los mapas de
teclado alemanes. Coordinación de esfuerzo: ¿quién la necesita? :-)
• Mathieu Lafon mejoró el mapa de teclado francés.
• Corregidos algunos fallos del sistema de reserva de voces MIDI.
• Añadida ls opción -k (guarda nombres) a la utilidad dat.
• El programa de setup ahora usa la variable de entorno ALLEGRO para localizar el
fichero keyboard.dat.
• Solucionado un problema con los carácteres < y > de la documentación HTML.

Cambios de 2.2 a 3.0 beta (Noviembre


1997)
• Se añadieron los parámetros de intrumentos de George mejorados para el driver
AWE32.
• La utilidad pat2dat ahora puede reducir samples de 16 a 8 bits (salva espacio, y el
driver DIGMID en todo caso sólo usa 8 bits).
• Se añadió otra versión del controlador del raton, esta vez en un intento de que
funcione mejor bajo Windows NT.
• Frodo Baggins añadió un mapa de teclado portugués.
• Se añadió la función "shell" como herramienta externa al grabber.
• Se añadió la función "box grab" al grabber, la cual usa el color #255 para
determinar los bordes de un sprite a seleccionar.
• Santeri Saarimaa añadió un mapa de teclado finlandés.
• La utilidad pat2dat por fin está completa, y el driver DIGMID ahora funciona
mucho mejor.
• Mathieu Lafon añadió soporte para las teclas Pausa e Imprime Pantalla, y cambió el
array key[] a un campo de bits que indica si una o varias teclas normales y
extendidas están siendo pulsadas. Esto sigue siendo compatible con la sintaxis "if
(key[KEY_*])", pero también permite distinguir entre, por ejemplo, la tecla Enter
del teclado numérico y la que está al lado de la tecla shift (mayúsculas).
• Solucionado un fallo con el manejo de las variables de configuración que no
corresponden a ninguna sección.
• El fichero makefile ahora intenta detectar y avisar a la gente de los errores de
instalación más comunes.
• La versión HTML de la documentación ahora usa la extensión corta .htm si es
creada en un sistema con LFN desactivado.
• Los ficheros de mapas de teclado ahora solo salvan las teclas que son diferentes del
mapa de teclado de EE.UU. ¡Esto hace los mapas de teclado mucho más pequeños!
• Se ha cambiado la fuente y el mapa de teclado por defecto que usa la página de
códigos 437 del DOS al estándar ISO (primera parte de Unicode). Si tienes una
configuración de teclado usando la página de códigos antigua, ésta tendrá que ser
actualizada, pero no te preocupes, tengo un script que puede hacer esto fácilmente.
• Corregido un fallo con la detección de los formatos de fuentes (fijas o
proporcionales) cuando se recogen desde un fichero bitmap.
• Se ha añadido un punto modificable de repetición al reproductor MIDI (gracias a
George por solucionar esto...)
• Se reescribió el controlador del ratón para que dé la posición usando sólo los
contadores mickey del driver con int 0x33. Ojalá esto solucione el problema de los
drivers defectuosos de Logitech...
• Añadida la variable mouse_pos conteniendo los valores de los ejes X e Y en un
espacio de 32 bits, para permitir leerlos de una vez durante bucles rápidos.
• El grabber ahora puede hacer selecciones múltiples y tiene un nuevo comando
"ungrab" que copia de un objeto bitmap al portapapeles (puedes usar esto para hacer
paletas de imágenes truecolor, o para re-grabar un área más pequeña de la imagen).
• Se añadió la posibilidad de hacer múltiples selecciones en el objeto lista GUI.
• Theuzifan mejoró la detección de cpu para chips Cyrix.
• Mathieu Lafon añadió un mapa de teclado francés.
• Richard Mitton escribió un programa de ejemplo demostrando como emular un
modo de color de 12 bits truecolor en una tarjeta de 8 bits.
• Michal Mertl añadió una rutina para generar paletas optimizadas para una imagen
truecolor específica.
• Se han optimizado las funciones getr/g/b(). Convertir ahora imágenes de diferentes
profundidades de color debería de ser mucho más rápido ahora.
• Scott Harrison añadió código para detectar OpenDOS, y se usa el modo i_love_bill
si su versión de EMM386 está en uso.
• Se añadieron algunos programas de ejemplo.
• La utilidad makedoc ahora convierte los códigos de caracteres de DOS a los
extendidos de Windows al crear ficheros HTML.
• Ettore Perazzoli optimizó espectacularmente la función blit lineal del modo-X.
• Se añadió una opción grid a la utilidad dat, para especificar que región del bitmap
quieres coger.
• Arreglado el fallo al dibujar bitmaps truecolor en bitmaps de modo-X.
• Arreglado el fallo que impedía cambiar el volumen de la tarjeta Adlib cuando sólo
los drivers MIDI estaban instalados.
• El grabber se puede ejecutar en otros modos de vídeo que 64x480 (sin embargo, no
es muy bonito en resoluciones bajas :-)
• Se añadió un nuevo scancode falso para la tecla extendida / (la del teclado
numérico) para que las dos teclas puedan ser distinguibles.
• Joaquin Hierro Díaz hizo un mapa de teclado español.
• La utilidad de setup se puede usar ahora para seleccionar un mapa de teclado y para
calibrar el joystick, así como para el hardware de sonido.
• Moví algunos documentos a otros sitios, para que la gente ojalá encuentre más
rápido el fichero faq.txt, y para acercarme al modo de distribución estándar de
GNU.
• Mejorado el sistema de configuración de teclado. Ahora hay una utilidad para
seleccionar el mapa de teclado, y éstos pueden ser leídos desde ficheros externos, y
soportan correctamente las teclas alt-gr y los acentos.
• Los ítems de los menús ahora se pueden desactivar, tienen ahora signos de marcado,
pueden alinearse el texto a la derecha para enseñar atajos de teclado, hay un nuevo
campo "void *dp" en la estructura del menú, y hay rutinas de clickeado callback
usan el puntero global "active_menu" para determinar qué opción fue llamada, si
alguna rutina es compartida por varios ítems de menú.
• Peter Palotas añadió un callback de entrada a las rutinas de teclado, y banderas de
evento al callback del ratón.
• Se añadió la opción -pal a la utilidad dat.
• Grzegorz Ludorowski hizo algunos gráficos nuevos para la demo.
• Se movió parte del código a nuevos ficheros y se añadieron varios macros para que
puedas quitar drivers de gráficos y sonido en el momento de enlazar tu programa.
• Fabian Nuñez añadió soporte para el joystick Logitech Wingman Extreme.
• Chris La Mantia contribuyó con un objeto de diálogo d_slider_proc().
• Sean Gugler añadió una rutina para cambiar el estado de los LEDs del teclado.
• Gearge Foot añadió funciones de pausa y búsqueda al reproductor MIDI.
• Se añadió la posibilidad de unir ficheros de datos (de hecho, cualquier fichero) al
final de tu programa ejecutable.
• Se incluyó del driver de la AWE32. ¡Larga vida a George!
• Ahora se pueden leer ficheros TGA con compresión RLE.
• Se añadió una función de callback de movimiento para el ratón (útil para detectar
eventos de doble click).
• Stefan Eilert añadió soporte para dos joysticks.
• Seymour Shlien contribuyó una rutina para dibujar texto justificado.
• Krzysztof Krzyzaniak contribuyó un cargador de ficheros .VOC.
• Se añadió la función rotate_scaled_sprite().
• Ahora hay soporte para teclados Dvorak.
• Salvador Eduardo Tropea añadió el modo VGA 320x100.
• Se implementaron funciones para dibujar ficheros RLE translúcidos e iluminados en
los modos truecolor.
• Se actualizó el la utilidad de setup de sonido.
• La utilidad dat puede crear ficheros makefile para poder reconstruir un fichero
automáticamente cuando un fichero fuente cambia.
• Se solucionaron algunos problemas de las funciones de conversión RGB <-> HSV.
• Soporte truecolor añadido al grabber y al cargar imágenes.
• Phil Frisbie añadió código para detectar el tipo de CPU.
• Michal Mertl añadió los modos gráficos de 24 bits. ¡Hurra!
• Se añadieron funciones para reproducir canales de datos de audio digital.
• Chris La Mantia contribuyó un objeto de icono bitmap GUI.
• Doug Eleveld añadió un objeto de caja de texto GUI, y un sistema mejorado de
ayuda para el grabber.
• Ahora se soportan los mapas de teclado UK y AZERTY. Se pueden añadir más
fácilmente si me mandas la tabla scancode -> ASCII apropiada...
• Se añadieron las funciones get_align_matrix(), qtranslate_matrix(), y
qscale_matrix().
• Se añadió la función draw_character() para usar sprites como máscaras monocromas
de pixel.
• Ahora es seguro pasar la misma matriz como entrada y salida de la función
matrix_mul().
• Paul Bartrum contribuyó algunas funciones para dibujar elipses.
• Se añadieron callbacks al driver MIDI, permitiéndote introducir tu propio código en
las notas midi o marcas de eventos.
• Se añadió una función para medir el movimiento del ratón en mickeys (diferencia
desde la última llamada) así como en coordenadas absolutas de pantalla.
• VolkerOth posibilitó el scroll de los objetos d_edit_proc, si la cadena de texto es
más larga que el espacio disponible.
• Se añadió la habilidad de distinguir entre las teclas izquierda y derecha de Control y
Alt.
• Fabian Nuñez añadió soporte para las teclas extra del teclado Microsoft.
• Se añadieron los campos *dp2 y *dp3 a la estructura de diálogo. Esto no debería
romper código existente, pero te permitirá almacenar más datos cuando crees
objetos propios.
• Las funciones packfile ahora pueden abrir y leer objetos de un fichero de datos,
usando nombres falsos de la forma "nombre.dat#nom_objeto". Esto significa que
todas las rutinas de Allegro de acceso a ficheros (como load_pcx() o
set_config_file()) pueden leer de objetos de ficheros de datos al igual que de
ficheros individuales.
• Se añadieron los programas miditest y digitest para permitir un testeo más riguroso
de las rutinas de sonido y los patches, y el programa vesainfo para chequear a qué
resoluciones se puede acceder en una tarjeta de vídeo.
• Jan Hubicka escribió una versión más rápida de create_rgb_table().
• La utilidad grabber ahora escala la vista previa de un bitmap si la imagen es
demasiado larga para caber en la pantalla.
• Jorrit Rouwe incorporó nuevas y mejores definiciones de instrumentos FM al driver
MIDI de Adlib.
• Se añadió una función para cargar patches .IBK para uso del driver Adlib.
• Se añadió el directorio allegro/ a la estructura del árbol del fichero zip, por lo que
ahora puedes descomprimir Allegro en tu directorio djgpp.
• Richard Mitton añadió soporte para joysticks con 6 botones.
• Modos gráficos truecolor (15, 16, y 32 bits).
• Rutinas de sonido vastamente mejoradas (API más flexible, ahora soporta hasta 32
voces simultáneas en la SB, driver MIDI basado en samples, puede invertir samples,
hacer efectos de volumen/pan/pitch, los comandos MIDI se pueden ejecutar en
tiempo real así como desde un fichero, y muchas más cosas).
• Ahora se puede actualizar el estado de los diálogos GUI de forma ascendente desde
tus propios bucles de control, con la función update_dialog(), en vez de pasar el
control totalmente a do_dialog().
• Los ficheros comprimidos (incluyendo ficheros de datos) pueden ser encriptados
con un password.
• Añadida la función masked_blit(), que ignora los pixels cero.
• Se añadió código para detectar la ejecución bajo Linux DOSEMU, y en ese caso se
usa una versión del código de temporización que usa menos recursos.
• Se añadió un mecanismo de configuración estandarizado. El formato para la
información salvada de calibración de joystick ha cambiado, por lo que los ficheros
de joystick existentes ya no son válidos.
• Se añadió la rutina textprintf(), que usa un formato de cadena como printf().
• Se añadió una versión TexInfo de la documentación ((gracias por la ayuda,
Francois!)
• Jonas Petersen añadió la función save_bmp(), y añadió soporte para el formato
BMP de OS/2.

Cambios de 2.11 a 2.2 (Febrero 1997)


• TBD/FeR añadió las resoluciones 320x600 y 360x600 al driver de modo-X.
• Matthew Bowie añadió soporte para joysticks de 4 botones.
• Dave Thomson añadió funciones de conversión RGB <-> HSV.
• Se añadió la variable ''freeze_mouse_flag', que puede ser usada para congelar el
puntero a una posición específica.
• Se añadió la variable 'key_led_flag', que ahora puede ser usada para evitar que el
LED de estado de las teclas bloq.mayús, bloq.num y scroll-lock cambie.
• El reproductor midi ahora inicializa midi_pos a -1 cuando la música acaba de tocar.
• Adrian Oboroc escribió una función para cargar LBM.
• Las fuentes ahora pueden contener caracteres ASCII por encima de 127.
• Chris Wigman hizo una intro mejor para el juego demo.
• Se añadieron rutinas de translucencia, mezcla de color e iluminación (basadas en
código de Owen Embury e ideas de Nathan Albury).
• Se añadieron funciones matemáticas 3d y de manipulación de matrices.
• Se añadieron dibujadores de polígonos texturizados y con sombreado goraud.
• Tim Gunn contribuyó código para leer y escribir ficheros TGA.
• Se arreglaron los problemas de los sprites rotatorios no circulares.
• Se añadieron barras de desplazamiento al objeto GUI listbox.
• Seymour Shlien escribió una función para dibujar curvas bezier.
• Se añadieron las funciones de punto fijo fadd() y fsub(), que chequean el
desbordamiento.
• Se añadieron las funciones pack_fseek() y manipulación de chunks a las rutinas de
ficheros.
• Se mejoró la estructura de los ficheros de datos y el programa grabber.
• Se escribió una utilidad para convertir ficheros de datos del grabber en código asm
enlazable.
• Salvador Eduardo Tropea mejoró las rutinas de teclado (mejor manejo de scancodes
extendidos, soporte de LED del teclado, y detección de bloq.mayús, bloq.num y
alt+teclado numérico).
• Se arreglaron las funciones packfile y el selector de ficheros para que funcionen con
los nombres largos de win95.
• Seymour Shlien contribuyó un lector de ficheros BMP.
• Añadida una función de enganche al código de teclado, permitiéndote usar código
GUI sin instalar el controlador de teclado.
• Solucionado el cuelgue producido por intentar acceder a unidades de disco no
existentes.
• Francois Charton escribió un driver para la tarjeta gráfica Paradise.
• Chris La Mantia contribuyó el botón de radio de diálogo GUI y añadió la bandera
de objeto D_DISABLED.
• Markus F.X.J. Oberhumer arregló las funciones de scroll de Video-7.
• Se convirtió la documentación en formato HTML.
• Se añadió código para detectar Windows NT.
• Mark Habersack añadió soporte para nuevos chipsets Trident.
• Se trabajó más en el driver VBA/AF (ahora funciona, pero todavía no soporta
funciones de aceleración por hardware).
• Arreglados los fallos del reproductor FLIC y cargador de samples WAV.
• Se añadió el modo especial 'windows friendly' al código del temporizador. ¡Ahora
incluso puedes ejecutar demo.exe bajo Windows 3.1!
• Se reorganizó la estructura de directorios para permitir una versión Linux. El
fichero liballeg.a ahora se encuentra en lib/djgpp.
• Se añadió soporte para las fuentes de formato BIOS 8x16.
• Solucionado un problema de desbordamiento al rotar sprites grandes.
• Se arregló un problema con la recuperación del modo texto después de ejecutar
programas que usan Allegro.

Cambios de 2.1 a 2.11 (Noviembre 1996)


• Arreglado el fallo en el banco.S.
• install_mouse() ahora ajusta el rango a (0,0,SCREEN_W,SCREEN_H).
• install_sound() no ajusta automáticamente el volumen al máximo.
• Se añadieron los operadores ++ y -- a la clase fija.
• Makefile ahora copia liballeg.a a lib, y allegro.h a include.
• Se hicieron algunos cambios para trabajar con LFN=y (por si usas unzip o winzip
en vez de pkunzip).
• Se añadió el fichero manifest.
• Instrucciones de instalación clarificadas.

Cambios de 2.0 a 2.1 (Junio 1996)


• Soporte de modo-X (gracias a Jonathan Tarbox y Dominique Biesmans por sugerir
esto y luego ayudar a implementarlo).
• Sprites compilados.
• Jonathan Tarbox contribuyó un reproductor FLI/FLC.
• Se añadieron modos de dibujo con patrón.
• Se añadió un simulador de la interrupción de retrazo vertical.
• polygon() ahora puede manejar figuras cóncavas o con intersecciones. También se
cambiaron los parámetros un poco. Perdón si esto estropea tu código viejo, pero es
más eficiente de este modo.
• Añadido stretch_sprite().
• Se escribió la rutina floodfill().
• Rutinas de fundido de paleta más flexibles.
• Se añadió set_volume() al código de sonido.
• David Calvin escribió una utilidad para configurar el sonido.
• Mejorado el GUI. Se añadieron menús emergentes/de persiana, entrada de joystick,
cajas de alerta de tres botones, mejor manejo del foco con los cursores, un nuevo
objeto de atajo de teclado (d_keyboard_proc()), y el carácter '&' para marcar los
atajos de teclado. El GUI ahora puede ser usado con otras fuentes que no sean 8x8
al alterar el puntero global 'font'.
• Fabian Nuñez añadió soporte para el joystick CH Flightstick Pro (me gusta: quiero
uno :-) y el botón central del ratón.
• El mánager de teclado ahora responde al estado de las teclas ctrl y alt, y hay una
nueva función simulate_keypress().
• Mark Wodrich añadió sub-bitmaps, que comparten memoria con bitmaps padre y
pueden ser posicionados en cualquier lugar dentro de ellos, y tienen sus propios
rectángulos de clipping.
• Mask modificó el driver de ratón para hacer doble-buffer con el puntero (para que
no parpadeé más), y añadió la función set_mouse_sprite_focus().
• Se añadieron las funciones set_mouse_range() y set_mouse_speed().
• Gracias (de nuevo) a Mark Wodrich, el grabber ahora puede importar ficheros GRX
.FNT.
• El grabber ahora puede hacer backups al salvar ficheros de datos, y sólo escribe el
fichero de cabecera si el contenido ha cambiado, para prevenir la recompilación
innecesaria.
• Añadida la función text_height().
• Mejoradas las funciones de punto fijo de cosecante y secante. Ahora usan tablas
precalculadas, por lo que sin mucho más rápidas.
• Reorganizada la estructura de directorios, añadidos algunos programas de ejemplo y
mejorada la documentación.

Cambios de beta 2.0 a final (Marzo 1996)


• Marcel de Kogel arregló algunos problemas con el driver MPU-401. Ahora
realmente funciona :-)
• Marcel también mejoró los sonidos de batería del driver Adlib.
• Funciones fmul() y fdic() ahora en ensamblador.
• Función fsqrt() mucho más rápida, cogida de la librería de punto fijo/coma flotante
de Arne Steinarson.
• Funciones bmp_write_line(), bmp_read_line(), y _putpixel() en ensamblador.
• Las rutinas de teclado ahora soportan la secuencia de escape de emergencia
ctrl+alt+del, y hay mánagers de señales para asegurarse de que Allegro se cerrará
limpiamente si tu programa se bloquea.
• Nuevas funciones irq que ahora pueden tratar con interrupciones reentrantes.
• Se añadieron rutinas de joystick (basadas en código de Jonathan Tarbox y Marcel de
Kogel).
• Se movieron algunas funciones a otros ficheros y se cambiaron cosas para que el
enlazador haga un trabajo mejor. Si ahora no usas funciones de sonido o de gráficos,
no serán enlazadas a tu ejecutable.
• Marcel de Kogel consiguió localizar mi (terriblemente estúpido :-) error que no
permitía trabajar al driver lineal VESA 2.0.
• Varios correcciones de fallos y mejoras de rendimiento.
Cambios de 1.x a 2.0 beta (Enero/Febrero
1996).
• Dejé todo el código Borland. Hace unos meses se me acabó el espacio en el disco
duro, y ejecuté con gran satisfacción el comando 'deltree /y c:\bc4'. Era un
compilador horrible, y estoy orgulloso de que esté muerto.
• Se añadió soporte SVGA. Como resultado, ya no hay motivo para poner el sistema
en modo 13h con allegro_init(), por lo que estarás en modo texto hasta llamar
set_gfx_mode().
• Se añadió código de sonido (mezcla de samples y música MIDI de fondo).
• Se añadió soporte para fuentes proporcionales (de cualquier tamaño) al igual que las
antiguas fuentes fijas de 8x8.
• Modo de dibujo XOR.
• Ahora ya no existe la estructura SPRITE. El código de dibujo de sprites ahora
dibuja bitmaps sobre otros bitmaps, lo cual es un modo más flexible de hacer las
cosas. El lector de ficheros de datos convertirá tus viejos sprites a bitmaps al
cargarlos, por lo que la única diferencia práctica es que ahora las funciones de
dibujado de sprites no pueden dibujar sprites opacos (pero sigues pudiendo hacer un
blit).
• show() y get_sprite() ya no existen: usa blit() en su lugar.
• Se añadieron las funciones de dibujo de sprites rotados e invertidos.
• Se añadió el escalado de bitmaps.
• Se añadieron sprites RLE.
• drawsprite() ahora se llama draw_sprite().
• textmode() ahora se llama text_mode() para evitar conflictos con las definiciones de
conio.h.
• Todas las funciones de acceso a ficheros se han renombrado de la sintaxis de stdio a
pack_fopen(), pack_getc(), etc, para que puedan ser mezcladas con código que use
stdio.
• Se añadió pack_fgets() y pack_fputs().
• El puntero port_callback ya no existe.
• Eliminado polyline() (¿quién lo usaba?), y se añadió polygon(), que dibuja un
polígono convexo relleno con un número arbitrario de vértices.
• Se añadieron las funciones do_line() y do_circle(), que llaman una función del
usuario por cada pixel que necesita ser dibujado.
• Se añadió un interfaz de teclado por defecto a las rutinas GUI, permitiendo la
selección de objetos con los cursores y <enter>.
• Se añadieron algunos mensajes y banderas GUI. En particular ahora hay mensajes
para seguir el movimiento del ratón, un mensaje de espera, un valor especial de
retorno del mensaje MSG_CHAR que permite a un objeto ignorar el manejo por
defecto del teclado, y una bandera que oculta un objeto.
• Hay nuevas rutinas GUI para centrar el diálogo en la pantalla y para alterar los
colores usados por los diálogos estándar de alerta y selección de ficheros.
• El selector de ficheros ahora acepta un tercer parámetro que especifica el tipo de
extensión a enseñar.
• Las rutinas de reloj ahora tienen mejor grado de precisión que un milisegundo, y
ahora es posible alterar la velocidad de una rutina callback de reloj en tiempo real
(reinstalándola con un nuevo valor de velocidad).
• Se eliminó la estructura _RGB y las funciones paltorgb(). Los RGB's ahora se
almacenan directamente en el formato de hardware, cada uno con un valor en el
rango 0-63.
• Se añadieron funciones para coger y escribir entradas de paleta individuales al igual
que paletas enteras.
• Se añadió código para fijar (lock) memoria DPMI.
• Se escribió la clase 'fija' C++ que sobrecarga muchos operadores, permitiéndote
usar las rutinas de punto fijo fácilmente.
• Probablemente hay muchas más cosas que he olvidado.

El Hall de la Fama
Espero haberme acordado de todos los que deban ser mencionados aquí. Si su nombre no
está aquí, pido perdón, ¡y por favor, digamelo para que pueda corregir mi fallo!

Colaboradores
A.Cottrell (andrewc@dbworld.net.au).
Cambió el grabber para que usase un formato de tiempo más robusto (indepentiente
localmente).

Adrian Oboroc (doba@corefx.com).


Escribió la rutina para cargar ficheros LBM.

Alex Demko (alex_demko@mbnet.mb.ca).


Sugirió muchas mejoras al sistema de ficheros de datos, y contribuyó código para manejar
el formato 8x16 de las fuentes BIOS.

Alessandro Monopoli (almonopo@tin.it).


Tradujo al italiano los mensajes de sistema.

Andreas Kluge (bitland@aol.com).


Escribió el controlador de la Ensoniq Soundscape y corrigió un fallo de división en la clase
de punto fijo.
Andrei 'old-boy' Ellman (ellman@xs4all.nl).
Contribuyó la función polygon_z_normal().

Andrew Ellem (krand@ican.net).


Escribió la versión original del código de flujo de audio digital.

Andrew Geers (andy@geerswj.clara.net).


Añadió las opciones -ppassword y -nosound al grabber, soporte de scroll en el visualizador
de imágenes, y las rutinas de sprites rotados e invertidos.

Andy Goth (andygoth@vetec.com).


Hizo la variable de configuración gfx_card más flexible, añadió un modo VGA trucado de
256x256, y escribió el objeto de diálogo d_text_list_proc().

Angelo Mottola (a.mottola@libero.it).


Añadió a BeOS el driver de joystick, MIDI, modo gráfico en ventana, soporte de la
ruedecilla del ratón, botón de cierre y soporte para cambiar de modo, y escribió el
controlador DGA2 para X y el soporte para el botón de cierre. Contribuyó la utilidad
bfixicon. Añadió soporte de triple buffer al port BeOS y añadió soporte fetch_mode_list()
para los drivers BeOS y DGA2 a pantalla completa. Ah, y contribuyó también el port de
QNX.

Annie Testes (email desconocido).


Añadió ganchos font_height, render_char, y char_length a FONT_VTABLE. Corrigió
varios problemas con el soporte unicode. Añadió la función pack_fdopen(). Detectó un
desorden en la secuencia de cierre de sistema bajo X. Descubrió cadenas ASCII que debían
ser convertidas.

Antoine Mathys (mmathys@bluewin.ch).


Añadió el mapa de teclado suizo.

Anton Ragnarsson (anton.ragnarsson@swipnet.se).


Contribuyó el mapa de teclado Sueco.

Antti Haapala (ztane@lyseo.edu.ouka.fi).


Corrigió el programa de setup para que enseñe la lista de frecuencias correcta para cada
tarjeta de sonido, y tradujo el sistema de mensajes al finlandés.

Antti Koskipaa (antti.koskipaa@nic.fi).


Escribió el driver DOS para las tarjetas WSS (Windows Sound System).

Arne Steinarson (arst@ludd.luth.se).


La rutina raiz de punto fijo vino de su biblioteca fija-flotante.

Attila Szilagyi (attilabox@hotmail.com).


Corrigió el scroll horizontal con SVGAlib.
Ben Chauveau (bendomc@worldnet.fr).
Añadió soporte para las tarjetas Tseng ET6000 (ahora disponible como parte del proyecto
FreeBE/AF).

Ben Darnell (bdarnell@vnet.net).


Agrupó y lanzó la versión 2.11 de Allegro mientras estuve alejado de la red, y escribió la
versión original del FAQ de Allegro.

Ben Davis (entheh@users.sf.net).


Añadió set_volume_per_voice(), programó el mezclador para que las voces silenciadas no
se congelen, y corrigió otros fallos del mezclador. Corrigió un fallo en create_rgb_table().
Adaptó las funciones de polígonos para que manejen vértices coincidentes. Añadió el
esqueleto de set_window_close_button() y set_window_close_hook(). Añdió soporte para
temporizadores con parámetros bajo Windows.

Benjamin Joel Stover (stovertech@intellisys.net).


Escribió la versión inicial del driver gráfico a pantalla completa de X.

Bertrand Coconnier (bcoconni@club-internet.fr).


Modificó las rutias en poly3d.c para obtener precisión de subpixel y subtexel. Mejoras de
velocidad en las funciones de polígonos. Corrigió el blending en la versión C las funciones
de scanline atex_lit, y añadió subdivisión de scanlines en las funciones scanline en C y las
funciones de polígonos con Z-buffer. Mezcló la librería P3D de Calin Adrian.

Burton Radons (loth@gec.net).


Optimizó las funciones de fundido de pixels truecolor, convirtió los blenders al nuevo
formato de un manejador, y añadió el rango de funciones blender compatibles con
Photoshop.

Calin Andrian (calin@ibd.dbio.ro).


Escribió las rutinas de renderización de polígonos truecolor en modos MMX, 3DNow!,
masked lit, translúcidas, las rutinas de render de polígonos con Z-buffer, la función
clip3d_f() y las funciones de ordenación de scanlines para el render 3D de escenas. Su
librería P3D fue fusionada con Allegro.

Calvin French (frenchc@home.com).


Añadió el parámetro -w (actualizar siempre) a dat.exe.

Carsten Schmidt (email unknown).


Escribió la versión inicial del driver GGI para Linux.

Carsten Sorensen (csorensen@ea.com).


Escribió el driver para la tarjeta de sonido ESS AudioDrive.

Cloud Wu (cloudwu@263.net).
Optimizó las funciones de fundido de pixels truecolor.
Chris Graham.
Sugirió añadir un nuevo bit para ficheros comprimidos NTFS en Windows.

Chris La Mantia (celamantia@home.com).


Escribió los objetos de diálogo d_radio_proc(), d_icon_proc(), and d_slider_proc(), añadió
la bandera D_DISABLES, mejoró el control GUI sobre diferentes alturas de fonts y añadió
las funciones de texto con alineación a la derecha.

Chris Robinson (crobin_99@yahoo.com).


Escribió la función en punto fijo clip3d().

Christian Schueler (cschueler@gmx.de).


Cambió las opciones de optimización para mejorar el rendimiento.

Daniel Nilsson (daniel7@algonet.se).


Incrementó el campo de estrellas de exstars, y corrigió el rango incorrecto de exlights.

David A. Capello (dacap@users.sourceforge.net).


Hizo que dotted_rect() evite los cambios de bancos. Corrigió un problema con clicks de
ratón perdidos en la GUI. Hizo que d_menu_proc robe y devuelva el foco cuando es
activado/desactivado y corrigió un problema con los submenús.

David Kuhling (dkuelhin@hell1og.be.schule.de).


Optimizó la rutina fsqrt(), y añadió fhypot().

Dave Thomson (gameskitchen@geocities.com).


Añadió las rutinas de conversión RGB <-> HSV, la función autocrop al grabber, y escribió
el programa ejemplo campo estelar 3d (exstars.exe).

David Calvin (calvid@rpi.edu).


Escribió la versión original de la utilidad setup de sonido.

Dmitriy Kazimirow (mariann@mail.ru).


Contribuyó el mapa de teclado y sistema de mensajes en ruso.

Dominique Biesmans (Dominique.Biesmans@ping.be).


Escribió la versión en modo-X de draw_sprite() y las funciones de blit de modo-X <->
modo lineal.

Doug Eleveld (D.J.Eleveld@anest.azg.nl).


Escribió el objeto de diálogo d_textbox_proc() y el nuevo sistema de ayuda del grabber.

Eduard Bloch (edi@gmx.de).


Corrigió un bloqueo causado por el código de detección ESD, corrigió un comportamiento
erróneo de las rutinas de configuración y sugirió mejores modos para encontrar la ruta del
ejecutable bajo Unix.
Edward Boone (Lucien.Boone@ping.be).
Proveyó las tablas de scancodes para un mapa de teclado AZERTY.

Elias Pschernig (eliaspschernig@aon.at).


Añadió el modo COLORCONV_KEEP_TRANS. Contribuyó la utilidad wfixicon.
Contribuyó varias mejoras al grabber.

Eric Botcazou (ebotcazou@multimania.com).


Hizo que el driver DGA funcione mejor en modos 8bpp y 32bpp, mejoró el driver DirectX
en ventana y el subsistema gráfico de Windows, parcialmente reescribió la API Unicode y
añadió uszprintf(), añadió file_select_ex(), la interfaz unificada al_find*(), un ejemplo
Unicode, un nuevo programa filetest, reescribió el script fixdll, cambió el proceso de
compilación para Borland C++, corrigió muchos errores y realizó toneladas más de trabajo
en el port Windows.

Erik Sandberg (eriksandberg@geocities.com).


Optimizó las funciones draw_sprite() y draw_trans_sprite() de 8 bits, y ayudó con la
traducción del sistema de mensajes al sueco.

Ettore Perazzoli (ettore@comm2000.it).


Optimizó las funciones blit modo lineal -> modo-X.

Evert Glebbeek (eglebbk@phys.uva.nl).


Puso set_gfx_mode a dieta y añadió una variable de configuración para especificar la
tarjeta a usar con GFX_AUTODETECT_WINDOWED.

Fabian Núñez (faybs@iafrica.com).


Añadió soporte para los joysticks CH Flightstick Pro y Logitech Wingman Extreme, el
tercer botón del ratón, y las teclas extendidas de un teclado Microsoft.

Fabrizio Gennari (faybs@iafrica.com).


Contribuyó los controladores de joystick DB9 y TurboGraFX.

Francois Charton (deef@pobox.oleane.com).


Escribió el driver gráfico para la Paradise (ahora disponible como parte del proyecto
FreeBE/AF), mejoró el código de ajuste de paleta de la VGA, y ayudó con la conversión
TexInfo de la documentación.

Frodo Baggins (l41273@alfa.ist.utl.pt).


Hizo el mapa de teclado portugués.

Garret Thomson (gart@terraport.net).


Escribió la música usada en el juego demo.

George Foot (gfoot@users.sourceforge.net).


Hizo una buena cantidad de trabajo para la versión consola de Linux. También escibió el
driver AWE32, añadió funciones MIDI de pausa/búsqueda, y proporcionó la base del lector
SoundFont usado en la utilidad pat2dat. Corrigió la función C fceil() y añadió la función
ffloor().

Gorka Olaizola (olsago@jet.es).


Añadió el fichero .spec del RPM RedHat.

Greg Hackmann (hacker@ididitmyway.com).


Contribuyó el port para Borland C++ Builder.

Grzegorz Adam Hankiewicz (gradha@users.sourceforge.net).


Escribió algunos programas de ejemplo, sugirió la opción "compress" del makefile, tradujo
el sistema de mensajes y la documentación al español, sugirió la idea de empotrar la
utilidad setup en otros programas, escribió algo de documentación, y corrigió la
generación .texi para mejorar la salida texi2dvi, mejoró la utilidad makedoc, añadió
reload_config_texts() y realizó bastantes cosas más.

Grzegorz Godlewski.
Contribuyó la localización al Polaco y añadió soporte para tablas altgr mayores y menores.

Grzegorz Ludorowski (pajonk@ajax.umcs.lublin.pl).


Escribió algunos programas de ejemplo, y la animación introductoria y los gráficos para el
juego demo.

Guilherme Silveira (thedarkage@geocities.com).


Modificó el seleccionador de ficheros para que sólo enseñase letras de unidad válidas.

Gunter Ladwig (gladwig@iname.com).


Escribió las rutinas de detección de OS/2.

Haruhiko Okumura, 12-2-404 Green Heights, 580 Nagasawa, Yokosuka 239, JP.
Escribió la versión original del código de compresión LZSS.

Henrik Schmidt.
Encontró una solución al problema de cambio de tarea bajo Windows.

Henrik Stokseth (hstokset@tiscali.no).


Contribuyó una versión nativa de Mingw32 que puede ser compilada con un compilador
cruzado o el compilador Cygwin. Mejoró la detección de SSOO. Añadió
get_gfx_mode_list() y métodos para preguntar a los drivers VGA, Mode-X, Xtended,
VESA, VBE/AF y DIRECTX una lista de los posibles modos gráficos. Reescribió el
selector de módo gráfico para que use get_gfx_mode_list(). Reescribió/actualizó algunos
scripts y modificó el proceso de compilación muchas veces.

Isaac Cruz (icruzbal@teleline.es).


Corrigió un fallo con el dibujado acelerado en sub bitmaps de superficies DirectDraw, y
añadió el controlador GFX_DIRECTX_WIN, corrigió el fallo del bloqueo de sub bitmaps
bajo Windows, añadió las rutinas desktop_color y yield_timeslice para Windows, y realizó
extensas modificaciones en otras partes del código de Windows.

Ivan Baldo (lubaldo@adinet.com.uy).


Escribió el código de difuminado 15/16 bits y optimizó las rutinas de rotación de sprites.

James Arthur (jaa@arfa.clara.net).


Documentó las rutinas de blending truecolor estilo Photoshop.

James Hyman (frooge@mindless.com).


Añadió soporte para cadenas entrecomilladas en la función get_config_argv(), y código
para difuminar imágenes con paleta.

Jan Hubicka (hubicka@horac.ta.jcu.cz).


Mejoró vástamente la velocidad de la función create_rgb_table().

Jason Wilkins (fenix at io dot com).


Escribió las rutinas matemáticas de quaternas, y contribuyó el port BeOS.

Javier Gonzalez (xaviergonz@hotmail.com).


Corrigió la velocidad del movimiento del ratón en Windows, hizo que allegro_message()
use el título de set_window_title(), añadió el soporte para el gancho de botón de cierre y
mejoró el cambio de aplicación en Windows, corrigió fallos al limpiar subbitmaps,
comunicó varios errores y sugerencias para mejorar Allegro. Contribuyó la reproducción
bidireccional con looping y hacia atrás del driver DirectSound. Corrigió un problema de
latencia con los flujos de audio.

Jim Flynn (jflynn@pacbell.net).


Quitó los cálculos en coma flotante del controlador MIDI AWE32.

Joaquin Hierro Díaz (Joaquin.Hierro.Diaz@fresno.csic.es).


Hizo el mapa de teclado español.

Joerg Rueppel (sharky-x@gmx.net).


Añadió al dat.exe mejores búsquedas de patrones en los nombres de los objetos y la función
find_datafile_object().

Johan Peitz (d98peitz@dtek.chalmers.se).


Corrigió y mejoró el driver de joystick Win32. Contribuyó el icono 'Alex the Allegator'.

Johan Venter (leonjventer@bigpond.com).


Corrigió algunos problemas con los makefiles para RSXNT y Mingw32.

Jonas Petersen (joXonoX@berlin.snafu.de).


Añadió la función save_bmp(), y soporte para el formato BMP de OS/2.
Jonathan Tarbox (jonattar@rocketmail.com).
Escribió el código de setup del modo-X, el reproductor FLI/FLC, y contribuyó partes del
controlador de joystick.

Jorrit Rouwe (j.rouwe@cpedu.rug.nl).


Contribuyó un nuevo y mejor conjunto de definiciones de instrumentos para el driver MIDI
Adlib.

Jose Antonio Luque (skylord@LatinMail.com).


Mejoró el controlador de joystick de Windows, y optimizó las funciones de 16 bits blit() y
masked_blit().

Joshua Heyer (joshua_heyer@yahoo.com).


Escribió la versión original del controlador de sonido OSS.

Keith Gerdes (kwg@softhome.net).


Corrigió el driver DirectDraw en modo overlay.

Kerry High (khigh01@umr.edu).


Contribuyó el controlador del pad de la SNES.

Kester Maddock (dmaddock@xtra.co.nz).


Escribió el controlador del joystick Wingman Warrior.

Knut Pape (Knut_Pape@t-online.de).


Mejoró el fichero readme para Mingw32.

Krzysztof Krzyzaniak (eloy@arrakis.cs.put.poznan.pl).


Escribió la función load_voc().

Laurence Withers (lwithers@lwithers.demon.co.uk).


Añadió un gancho de destrucción a la estructura font, trabajó en la corrección `const' por
toda la librería, implementó una nueva estructura FONT y redujo las dependencias de
enlazado de algunos módulos.

Lee Killough (email unknown).


Añadió la rutina gancho de bajo nivel al controlador de teclado, y corriguió un par de fallos.

Lennart Rolland (chimeni@hotmail.com).


Contirbuyó la traducción de los mensajes al noruego.

Lorenzo Petrone (_lano_@libero.it).


Contribuyó la utilidad gfxinfo y añadió dos respuestas al FAQ.
Lucas Vignoli Reis (lucasvr@bestway.com.br).
Añadió la traducción de los mensajes al portugués (Brazil) y añadió el mapa de teclado
correspondiente.

Maiolino Carmelo (cmaiolino@ctonline.it).


Añadió el mapa de teclado Italiano.

Manni Heumann (manfred.heumann@uni-bielefeld.de).


Corrigió algunos problemas con el mapa de teclado alemán.

Marcel de Kogel (m.dekogel@student.utwente.nl).


No contento con arreglar mi driver MPU-401, Marcel proveyó un conjunto de sonidos de
tambor mejores para el driver OPL, me ayudó con el problema de las interrupciones
reentrantes, aportó la mitad del código de joystick que no vino de Jonathan, y ayudó a
encontrar el estúpido fallo de mi código de framebuffer VESA lineal.

Marcel Smit.
Corrigió un fallo que causaba errores al dibujar polígonos con corrección de perspectiva
perpendiculares a la pantalla.

Marco Campinoti (marco@etruscan.li.it).


Añadió soporte de 15 y 24 bits al driver Tseng ET4000 nativo (ahora disponible como parte
del proyecto FreeBE/AF).

Marco Marmulla (Viper005@usa.net).


Añadió soporte de 16 bits a la rutina load_voc().

Marian Dvorsky (mdvorsky@dodo.sk).


Escribió las rutinas de interfaz GDI para Windows.

Marius Fodor (iceman@teleport.com).


Añadió soporte para el Sidewinder y el Gravis Gamepad Pro.

Marek Habersack (grendel@ananke.amu.edu.pl).


Añadió soporte para los chipsets más recientes de Trident (ahora disponible como parte del
proyecto FreeBE/AF).

Mark Wodrich (mwodric@eleceng.uct.ac.za).


El cerebro detrás de los sub-bitmaps, punteros de ratón libres de parpadeo, y la habilidad
para importar ficheros GRX .FNT en el grabber.

Markus F.X.J. Oberhumer (markus.oberhumer@jk.uni-linz.ac.at).


Arregló la función de scroll de la Video-7 (ahora disponible como parte del proyecto
FreeBE/AF), optimizó las rutina de mapas de color, e hizo muchas sugerencias útiles como
el añadir el campo vid_phys_base a la estructura del driver de gráficos.
Martijn Versteegh (m.versteegh@hccnet.nl).
Añadió el mecanismo de extensión de enganche de la configuración.

Mathieu Lafon (mlafon@ifhamy.insa-lyon.fr).


Añadió el mapa de teclado francés, soporte para las teclas Pause/PrtScr, y cambió la tabla
key[] a un campo de bits normal/extendido.

Matthew Bowie (catcat@nmt.edu).


Añadió soporte para joysticks de 4 botones.

Michael Bevin (michael.bevin@stonebow.otago.ac.nz).


Optimizó la función create_trans_table().

Michael Bukin (M.A.Bukin@inp.nsk.su).


Optimizó el código de dibujo de líneas, solucionó un fallo en fadd()/fsub(), y contribuyó
_un montón_ de parches para mejorar la portabilidad y robustez de toda la biblioteca.

Michael Rickmann (mrickma@gwdg.de).


Portó el código Windows a Mingw32.

Michael Tanczos (webmaster@logic-gate.com).


Solucionó algunos fallos del reproductor de ficheros FLIC.

Michal Mertl (mime@eunet.cz).


Escribió todo el código de gráficos de 24 bits, optimizó la función para generar paletas, y
yn buen número de otras cosas truecolor (escalado de bitmaps, carga de imágenes, etc).

Nathan Albury, aka Rubicant (gt4558a@prism.gatech.edu).


Mejoró la rutina de fuego en examples/exflame.c (mi versión original realmente no parecía
fuego :-) y dió ideas extremadamente útiles sobre la implementación de traslucencia.

Neil Townsend (neil@robots.ox.ac.uk).


Mejoró la precisión de las rutinas de temporización, y añadió parámetros callback.

Nick Kochakian (nickk@worldnet.att.net).


Escribió el driver de entrada DirectSound.

Ole Laursen (98zOLaw@aalborghus.dk).


Contribuyó el mapa de teclado y mensajes de sistema daneses, e hizo que las funciones
Unicode utolower() y utoupper() entiendan el conjunto entero de carácteres de 16 bits.

Olly Betts (olly@muscat.co.uk).


Modificó el makefile de djgpp para que soporte compilación cruzada en una máquina con
Linux.
Owen Embury (owen@gememail.demon.co.uk).
Escribió parte del código de traslucencia/iluminación.

Owen Rudge (alleg@orudge.freeuk.com).


Contribuyó el script de recurso de versión DLL y añadió el script mkdata.bat.

Ove Kaaven (ovek@arcticnet.no).


Solucionó un fallo en el driver ATI mach64 (ahora disponible como parte del proyecto
FreeBE/AF), añadió soporte nativo truecolor y framebuffer lineal al driver ATI, contribuyó
el mapa de teclado Noruego, y añadió rutinas de entrada MIDI y audio a los drivers MPU y
SB respectivamente.

Patrick Hogan (patter@iname.com).


Escribió la función draw_gouraud_sprite().

Paul Bartrum (bartrum@xtra.co.nz).


Contribuyó las funciones de dibujado de elipses.

Paul Furber (paul@sprintlink.co.za).


Proveyó la función de coma flotante apply_matrix_f().

Paul Hampson (Paul.Hampson@Pobox.Com).


Mejoró y corrigió algunos problemas con el driver del pad de la SNES.

Paul Pinault (diskaleg@infonie.fr).


Tradujo el sistema de mensajes al francés.

Pavlos Touboulidis (gtoub@otenet.gr).


Hizo que file_select() sea capaz de incluír o excluír ficheros basándose en sus atributos.

Pedro Cardoso (pcardoso@viriato.ipv.pt).


Contribuyó el modo trucado VGA 80x80.

Peter Cech (7cech@nw.fmph.uniba.sk).


Añadio al grabber soporte para la fuente 8x8 de la BIOS, y soporte para intercambiar
mediante una combinación de teclas entre el mapa de teclado americano estándar y otro
mapa de teclado personalizado. Optimizó las rutinas de blending de sprites alpha. Añadió
reconocimiento de carácteres no-ASCII de espaciado a uisspace().

Peter Monks (pmonks@iname.com).


Escribió el driver de la Video-7 (ahora disponible como parte del proyecto FreeBE/AF), y
me enseñó cómo fijar el modo lineal 640x400.

Peter Palotas (blizzar@hem1.passagen.se).


Añadió la rutina callback del teclado.
Peter Pavlovic (Peter.Pavlovic@st.fmph.uniba.sk).
Añadió el mapa de teclado eslovaco y traducción de mensajes del sistema, impidió que el
selector de ficheros DOS mostrase unidades virtuales, hizo lo mismo para el selector de
ficheros de Windows, mejoró el soporte para mapas con carácteres acentuados en el
controlador de teclado, y realizó modificaciones estéticas al sistema de menús GUI.

Peter Puck (zaqhaq@netscape.net).


Ayudó con la versión Mingw32 del proceso de compilación.

Peter Wang (tjaden@users.sourceforge.net).


Añadió soporte para entrada de la ruedecilla del ratón (mouse_z) bajo Linux, corrigió
problemas con el controlador de sonido ESD, escribió el controlador de sonido ALSA, el
controlador de sonido BeOS, añadió soporte MIDI y entrada de samples al controlador
OSS, añadió soporte para modos con bancos al controlador SVGAlib, escribió el código de
cambio de modo para X DGA, mejoró el driver de joystick para Linux, X11 a pantalla
completa, los drivers DGA2 y DGA, añadió temporización con pthreads bajo Linux/Unix y
también realizó muchas más cosas.

Phil Frisbie, Jr. (pfrisbie@geocities.com).


Escribió el código de detección de la CPU.

Przemek Podsiadly (ppodsiad@elka.pw.edu.pl).


Añadió versiones hicolor del código de polígonos 3d.

Revin Guillen (revin@phylo.com).


Añadió la función position_dialog().

Richard Davies (richard@debaser.force9.co.uk).


Añadió soporte para los pads de PSX y N64.

Richard Mitton (100740.1271@compuserve.com).


Añadió soporte para joysticks de 6 botones, y escribió el programa de ejemplo de 12 bits de
profundidad (ex12bit.c).

Richard Reeve (r.e.reeve@stir.ac.uk).


Corrigió un fallo estúpido en la detección de gcc 3.0.x.

Robert J. Ragno (rjr@mit.edu).


Escribió el driver Gravis GrIP, y realizó mejoras al código de entrada del Wingman, PSX, y
palanca de velocidad.

Robert J. Ohannessian (voidstar_@excite.com).


Añadió optimización MMX para las rutinas clear() de 8 y 16 bits, y corrigió un fallo en la
limpieza de subbitmaps. También añadió detección de SSE y optimizó algunos
masked_blits con instrucciones SSE. Añadió algunas rutinas al conversor de colores
unificado. Reescribió el método de lectura de características de la CPU. También hizo
muchas más cosas.

Robin Burrows (rburrows@bigfoot.com).


Proveyó nuevo código de page flipping para el subsistema DirectDraw, añadió un
controlador de sonido Windows usando el mezclador de Allegro y otro usando waveOut.
Corrigió fallos en el código DirectDraw.

Romano Signorelli (romanos@bigfoot.com).


Añadió una rutina de dibujo de arcos.

Ronaldo Hideki Yamada (r.yamada@uol.com.br).


Contribuyó la versión Macintosh de Allegro.

S.Sakamaki (emt@geocities.co.jp).
Añadió el código VESA 3.0 de control de la velocidad de refresco.

S.Suzuki (s-suz@sunfield.ne.jp).
Escribió los controladores para las interfaces de joystick IF-SEGA /PCI, /PCI2, e /ISA.

Salvador Eduardo Tropea (salvador@inti.edu.ar).


Mejoró las rutinas de teclado (mejor control de los scancodes extendidos, soporte de LEDs
del teclado, bloq.mayús y bloq.num, y la entrada alt+ teclado numérico), contribuyó el
modo gráfico VGA 320x100, añadió soporte de mezcla de samples en 16 bits, Corrigió la
compilación con GCC 3.x e hizo numerosas sugerencias útiles, contribuciones y arreglos de
fallos.

Santeri Saarimaa (gridle@mbnet.fi).


Hizo el mapa de teclado finlandés.

Sask Allegro (sask_allegro@iespana.es).


Añadió soporte para más de dos joysticks en el port Windows.

Scott Harrison (scotth@calderauk.com).


Añadió el código de detección de OpenDOS.

Sean Gugler (sean@epal.com).


Añadió la función set_leds().

Seunghwan Ji.
Hizo que makedoc genere ficheros html y rtf correctos en Koreano.

Seymour Shlien (seymour@dgbt.doc.ca).


Contribuyó el lector de ficheros Windows BMP, dibujador de curvas bezier, y la función de
texto justificado.
Shawn Hargreaves (shawn@talula.demon.co.uk).
Progenitor. Escribió todo lo que no fue escrito por otra persona.

Stefan Eilert (seilert@rz.Uni-Osnabrueck.DE).


Añadió soporte para un segundo joystick.

Stefan Schimanski (1Stein@gmx.de).


Optimizó la función de blit reverso para bitmaps que se sobreescriben.

Stefan T. Boettner (virtual.man@t-online.de).


Escribió el driver SVGAlib para Linux.

Stepan Roh (src@srnet.cz).


Añadió el mapa de teclado y mensajes de sistema en checo, los carácteres Latin Extended-
A en la fuente por defecto, soporte para páginas de conversión en la utilidad textconv,
corrigió algunos problemas con el controlador de sonido ESD, y ayudó a compilar Allegro
en algunas plataformas Unix. Corrigió problemas relacionados con const en la versión C de
las rutinas de emsablador.

Stephen Kittelson (stickman2000@juno.com).


Made bugfixes and tweaks to the keyboard system.

Sven Sandberg (svsa1977@student.uu.se).


Solucionó el problema de redondeo de ancho de la imagen en save_bitmap(), optimizó la
rutina create_light_table(), optimizó las funciones trigonométricas de punto fijo, tradujo el
sistema de mensajes al sueco, mejoró el algoritmo de ordenación del selector de ficheros,
optimizó las rutinas de spline, añadió la función ustrrchr(), mejoró el manejo de floats en
usprintf(), cambió la API de Z-buffer, mejoró las rutinas de rotación y corrigió otros fallos.

TBD/FeR (tbd@usa.net).
Añadió las resoluciones 320x600 y 360x600 al driver de modo-X.

Teijo Hakala (teijo.hakala@imnetti.fi).


Añadió al driver de ratón bajo Windows soporte de la ruedecilla.

Tero Parvinen (Tero.Parvinen@hut.fi).


Diseñó gran parte del nuevo API de sonido.

Theuzifan Sumachingun (uzi@simauria.upv.es).


Mejoró la detección de cpu para chips Cyrix e hizo que el seleccionador de ficheros
mostrase sólamente letras de unidad válidas.

Thomas Wolf (two@chello.at).


Corrigió algunos errores en el mapa de teclado Alemán, y añadió la traducción alemana de
los mensajes de sistema.
Tim Bird (tbird@caldera.com).
Trabajó en el port de consola bajo Linux.

Tim Gunn (timgunn@eastwind.com.au).


Escribió las rutinas de lectura/escritura de ficheros TGA.

Timothy Terriberry (sundance@sprintmail.com).


Arregló varios fallos en las rutinas de conversión RGB <-> HSV.

Tom Breton (tob@world.std.com).


Añadió la selección funcional #ifndefs a allegro.h.

Tom Fjellstrom (tfjellstrom@home.com).


Escribió el controlador MIDI para ALSA.

Tom Novelli (tnovelli@cyber3.servtech.com).


Escribió la versión original del driver digital MIDI.

Tom St Denis (tomstdenis@yahoo.com).


Corrigió el recorte de objetos transparentes.

Tomohiko Sugiura (tmsugi@d4.dion.ne.jp).


Añadió las teclas KEY_ABNT_C1, KEY_YEN, KEY_KANA, KEY_CONVERT,
KEY_NOCONVERT y otras al controlador de entrada, y organizó la inclusión de los
controladores de joystick IF-SEGA de S.Suzuki en la distribución base. Añadió un
controlador de joystick Sidewinder más agresivo.

Vincent Penquerc'h (lyrian@kezako.net).


Añadió el bit D_DIRTY y eventos de pulsación/soltura de los botones del ratón al sistema
GUI, optimizó el código de blit de 256 colores a truecolor para evitar repetir conversiones
de la paleta, añadió scare_mouse_area(), la función yield_timeslice(), la función de
actualizar selección al grabber, las propiedades XCRP y YCRP a los ficheros de datos en
general, y realizó otras correcciones y mejoras. Responsable de la gran separación del
fichero de cabecera, también realizo muchas más cosas.

VolkerOth (VolkerOth@aol.com).
Integró los conceptos de scroll de objetos y el objeto edit_proc.

¡Gracias!
Primero, muchas gracias a todos aquellos que me han ayudado a probar y depurar el
código. A veces es frustrante recivir cientos de mensajes diciendo "¡no funciona!", pero
siguen siendo útiles...
Andre Baresel (baresel@informatik.hu-berlin.de), y Craig Jackson
(Craig.Jackson@launchpad.unc.edu), contribuyeron una cantidad tremenda de información
sobre el hardware de la SB.

Benji York (Benji@cookeville.com),


Proveyó información sobre el hardware del Gravis GamePad Pro.

Charles Mac Donald (cgfm2@hooked.net),


Me enseñó a ajustar algunas resoluciones geniales VGA y modo-X.

Charles Sandmann (sandmann@clio.rice.edu), DJ Delorie (dj@delorie.com), Eli Zaretskii


(eliz@is.elta.co.il), y todo el que haya contribuído a djgpp. Lo amo.

C. Schwerdtfeger (schwerdt@physics.ubc.ca), por su ayuda (¡y enorme paciencia!) en


conseguir hacer funcionar el driver MIDI de la SB Pro-I.

Finn Thoegersen, Nordbanevej 3 C, DK-7800 Skive, Denmark.


La mayoría de mi información sobre hardware SVGA vino de su paquete VGADOC.

Eric Jorgensen (smeagol@rt66.com).


Las Varmint's Audio Tools (VAT) me dieron muchas ideas útiles sobre cómo reproducir
ficheros MIDI.

Jamie O'Connell (JamieOConnell@msn.com).


Varios de los nuevos patches de tambores Adlib, y las especificaciones del formato .IBK
vinieron de su paquete SBTimbre.

Jean-Paul Mikkers (mikmak@stack.urc.tue.nl).


MikMod fue la fuente de mucha información sobre cómo programar la SB, y también me
dió la idea de reprogramar el PIT para conseguir un contador de realmente alta resolución.

Joel H. Hunter (jhunter@kendaco.telebyte.com).


Su librería SB para djgpp es excelente, me ayudó mucho.

John Pollard (74723.1626@compuserve.com).


Las definiciones de instrumentos FM están basadas en su biblioteca de funciones MID-
KIT.

Kendall Bennett y el resto de gente genial de SciTech Software.


Estos chicos dieron al mundo UniVBE, el API VBE/AF, y mucha información gratis y
ejemplos de código VESA. Además, me mandaron generósamente una copia de la
especificación VBE/AF cuando la quise.

Kris Heidenstrom (kheidens@actrix.gen.nz).


Su FAQ de temporización en PCs fue una gran ayuda.
Mark Feldman.
Ni si quiera hay que decir que PCGPE fue una fuente muy valiosa de recursos.

Michael Abrash.
Simplemente debes amar a ese hombre...

Paul Fenwick (bg914@freenet.carleton.ca).


Varias partes del código de modo-X (notablemente en la pantalla partida) vinieron de su
biblioteca de funciones XLIBDJ.

powerjaw (powerjaw@dnai.com).
Me mandó un pad Sidewinder para que pudiese corregir algunos problemas con el driver
para éste. Que cosa más genial que hizo...

Robert Grubbs (rwgrubbs@vt.edu).


Proveyó información sobre el hardware del joystick Sidewinder.

Robert Schmidt (robert@stud.unit.no).


Los valores de registro para las resoluciones 400x* del modo-X vinieron de su programa
TWEAK.

Tom Grandgent (tgrand@canvaslink.com).


Organizó y mantiene la lista de email de Allegro. ¡Hurra!

Vladimir Arnost (xarnos00@dcse.fee.vutbr.cz).


Proveyó las especificaciones de hardware del chip OPL3.

Frank Zappa, Mike Keneally, Pink Floyd, the Doors, Tori Amos, y demás artistas geniales
que me proporcionaron cosas para oír mientras programaba.

Mis padres, John and Nancy.


Nunca hubiese resistido aquellas sesiones de programación a altas horas de la noche sin la
cafetera que me regalaron las últimas navidades :-)

FAQ de Allegro
Si la respuesta no esta aquí, pregunte y será
añadida...

Contenido
• Problemas triviales
o ¿Cómo lo uso?
o ¿Dónde puedo conseguirlo?
o ¿Qué es Allegro?
• Problemas con DJGPP
o ¡Los errores de compilación aparecen demasiado rápido para que los
o ¿Qué es este programa make que se supone debo ejecutar?
o Cuando ejecuto make, dice "makefile has modification time in the future".
o Cuando ejecuto make, dice "virtual memory exhausted".
o Cuando ejecuto make, me pide unos parámetros. ¿Que debo teclear?
o Cuando intento compilar un programa usando Allegro, recibo muchos
o Make no funciona adecuadamente.
o Me doy por vencido: ¡No puedo compilar esto! Por favor, ¿podrías
mandarme
o Mi instalación de djgpp está bien, pero make todavía trabaja mal.
• Problemas en DOS
o ¡Obtengo el error "out of environment space" al ejecutar fix.bat o
o ¿Cómo puedo extender el limite de 256k de memoria de vídeo en Modo-X?
o ¿Funciona Allegro bajo OpenDos?
o ¿Funciona la versión DOS de Allegro bajo Windows NT?
o ¿Funciona la versión DOS de Allegro con la tarjeta de sonido SB-Live?
o ¿Por qué la versión DOS de Allegro reproduce los sonidos con menos
o ¿Por qué no funciona con mi tarjeta de vídeo?
o ¿Por que no usar algún tipo de sistema de enlazado dinámico?
• Problemas en Windows
o ¡Obtengo el error "out of environment space" cuando ejecuto fix.bat o
o ¡Obtengo errores sobre una función WinMain() o main() que falta!
o ¡Obtengo multitud de errores de compilación con
"LPDIRECTDRAWSURFACE2"!
o Obtengo cantidad de errores de compilación con
"DDEDM_STANDARDVGAMODES"!
• Probelmas Unix
o ¡Los errores de compilación aparecen demasiado rápido para que los
o ¡Obtengo errores sobre un "_mangled_main_address" no definido!
o Cuando intento usar DGA2, ¡la pantalla se pone negra y el PC se bloquea!
o Cuando intento usar DGA2, obtengo "resolution not supported", ¡pero el
• Problemas generales
o ¡No consigo que el objecto GUI d_icon_proc() funcione!
o ¡No consigo que la función rotate_sprite() funcione!
o ¡No consigo que las rutinas de polígonos en 3D funcionen!
o ¿Añadirás alguna vez soporte para las tarjetas aceleradoras 3D?
o ¿Cómo convierto la documentación en el formato de Ayuda de Windows?
o ¿Cómo es que en mi pantalla aparece un color en los bordes de mi monitor?
o ¿Cómo hago para que mi juego vaya a la misma velocidad en cualquier
o ¿Cómo puedo capturar una pantalla de mi programa que usa Allegro?
o ¿Cómo puedo convertir mis gráficos para que usen la misma paleta de 256
o ¿Cómo puedo dibujar diferentes imágenes el mismo tiempo? Cuando dibujo
la
o ¿Cómo puedo generar animaciones en formato FLI o FLC?
o ¿Cómo puedo generar un número aleatorio?
o ¿Cómo puedo hacer partes de mis sprites transparentes en modos
o ¿Cómo puedo hacer un fundido de pantalla en un modo gráfico truecolor?
o ¿Cómo puedo imprimir la documentación?
o ¿Cuando se terminará Allegro? No puedo esperar...
o ¿Dónde puedo encontrar ejemplos de código fuente de programas que usan
o ¿Dónde puedo encontrar fuentes para usar con Allegro?
o ¿Dónde puedo encontrar un conjunto de samples de instrumentos para el
o ¿Debo usar bitmaps, sprites RLE o sprites compilados?
o ¿Por qué hacer una espera activa del array key no funciona? Por ejemplo,
o ¿Por qué no añadir soporte de red?
o ¿Por qué no añadir una función de reproducción de MODs?
o ¿Por qué no hacer una versión "lite" de Allegro? No necesito ninguna de
o ¿Por qué no puedo leer ficheros GIF con Allegro?
o ¿Por qué parece que vsync() no funciona?
o ¿Por qué se considera buena práctica en programación el definir PI como
o ¿Puedo usar Allegro con mi compilador <foobar>?
o ¿Puedo usar Allegro en mi programa comercial?
o ¿Qué es eso de "Allegro WIP" que otras personas no dejan de mencionar?
o Consequí el parche WIP, pero no lo puedo aplicar.
o Cuando compilo Allegro, el make falla con algo como `Error: operands
o Cuando ejecuto la demo, dice que no puede encontrar demo.dat.
o Estoy intentando compilar el programa grabber, ¡pero no funciona!
o He intentado usar fade_in() y fade_out() en modos truecolor pero no
o Mi programa se bloquea todo el tiempo. ¿Puede ser debido a un fallo de
o Mis colores siempre salen mal. ¿Cómo puedo hacer una paleta de grises con
o Todavía estoy confundido. ¿Dónde pueden ayudarme?

Problemas triviales
¿Qué es Allegro?

Lea readme.txt.

¿Dónde puedo conseguirlo?


De cualquier mirror de SimTel, en el directorio gnu/djgpp/v2tk/, o desde la página web de Allegro, http://alleg.sourceforge.net/.

¿Cómo lo uso?
Lea allegro.txt.
Problemas con DJGPP
¿Qué es este programa make que se supone debo ejecutar?
Make es parte de la distribución estándar de djgpp, en v2gnu/mak*b.zip (el numero de la ultima versión). Puede obtenerlo de http://www.delorie.com/djgpp/.

Make no funciona adecuadamente.

¿Está
seguro
de que
tiene
djgpp
instalad
o
correct
amente
?
Revise
las
instrucc
iones
del
fichero
de
djgpp
readme.
1st, y
en
particul
ar cuide
haber
ajustad
o la
variabl
e de
entorno
de
DJGPP
y añada
el
director
io
djgpp\b
in a su
path.
Mi instalación de djgpp está bien, pero make todavía trabaja mal.
¿Está
seguro
de estar
usando
el
progra
ma
make
de
GNU,
en vez
de
algún
otro
como el
de
Borland
? Si no
lo sabe,
ejecute
"make
-v" y
compru
ebe que
visualiz
a el
mensaje
de
copyrig
ht de
GNU.
Cuando ejecuto make, me pide unos parámetros. ¿Que debo teclear?
¡No
debería
ejecutar
make
desde el
explora
dor de
Win95!
Abra
una
sesión
de DOS,
vaya al
directori
o de
Allegro,
y
ejecute
"make"
desde la
línea de
comand
os.
Cuando ejecuto make, dice "makefile has modification time in the future".
¿Seguro
que
tiene la
fecha
del
sistema
ajustada
correcta
mente?
Cuando ejecuto make, dice "virtual memory exhausted".
Tal y
como el
mensaje
de error
sugiere,
necesita
liberar
más
memoria
para el
compilad
or. El
program
a go32-
v2 le
dirá
cuanta
tiene
disponibl
e. Si está
en DOS,
intente
liberar
espacio
de disco
duro
para los
ficheros
temporal
es. Bajo
win95,
incremen
te el
límite de
memoria
DPMI en
las
propieda
des de su
sesión
DOS a
65535
(tendrá
que
escribir
esto a
mano, ya
que la
lista
desplega
ble sólo
llega
hasta
16384).
Cuando intento compilar un programa usando Allegro, recibo muchos
errores como:
C:\TEMP\ccdaaaaa(.text+0x9):x.c: undefined reference to `allegro_init'
C:\TEMP\ccdaaaaa(.text+0xe):x.c: undefined reference to `install_keyboard'
No ha
leído los
manuales
, ¿lo
hizo? :-)
Necesita
enlazar
su
programa
con la
bibliotec
a de
funciones
,
liballeg.a
.
Primero,
asegúrese
de que ha
instalado
todo
correcta
mente
(ejecutar
make
debería
hacer
esto por
usted).
Segundo,
si esta
compilan
do desde
la línea
de
comando
s o desde
un
makefile,
añada
-lalleg al
final de
su línea
de
comando
de gcc, o
si esta
usando
Rhide,
vaya al
menú
Options/
Libraries,
entonces
teclee
'alleg' en
la
primera
línea
vacía, y
asegúrese
de que la
caja al
lado esta
marcada.
Me doy por vencido: ¡No puedo compilar esto! Por favor, ¿podrías mandarme
una versión precompilada?
No, lo
siento.
Para
empezar,
liballeg.a
ocupa
unos
450k,
pero
probable
mente
querrá
varias
utilidades
como el
grabber,
la
configura
ción de
sonido,
etc. ¿Y
que hay
de los
programa
s de
ejemplo?
Si
incluyese
la versión
compilad
a de todo,
la
distribuci
ón binaria
sobrepasa
ría las 7
megas:
¡demasia
do grande
para ser
práctico!
Pero
seriament
e, no hay
ninguna
razón por
la que no
pueda
compilar
la librería
usted
mismo.
El
compilad
o de un
programa
es un
proceso
determini
sta: dado
un
fichero de
entrada
particular
y una
línea de
comando,
siempre
producirá
la misma
salida. Si
esto no
funciona,
o tiene
ficheros
de
entrada
incorrecto
s (su
copia de
Allegro
esta
estropead
a en
algún
sentido),
o la línea
de
comandos
es
incorrecta
(es difícil
que eso
suceda,
ya que
solo tiene
que
teclear
"make"...)
o su
compilad
or está
estropead
o, por
ejemplo,
si no
instala
djgpp
correctam
ente.
Necesita
soluciona
r el
problema
en vez de
ocultarlo
bajo la
alfombra
consiguie
ndo que
otro
compile
Allegro
por
usted...
¡Los errores de compilación aparecen demasiado rápido para que los
pueda leer!
Las
herramien
tas GNU
escriben
los
mensajes
de error a
stderr.
Desafortu
nadament
e,
command.
com es
demasiad
o estúpido
para
redirijir el
flujo, pero
afortunad
amente DJ
fue
suficiente
mente
listo para
evitar
esto, por
lo que
puede
usar su
programa
redir para
capturar
los
mensajes
de salida,
por
ejemplo
"redir -eo
make >
logfile.txt
".
Problemas en DOS
¿Funciona la versión DOS de Allegro bajo Windows NT?

Las
respuestas
pueden
variar.
Algunas
personas
dicen que
hay
problemas
, mientras
que otras
dicen que
todo
funciona
bien.
Personalm
ente no
tengo
acceso a
NT, por lo
que no
hay nada
que pueda
hacer por
esto, y
para ser
sincero,
no me
importa
mucho :-)
Si quiere
ejecutar
programas
DOS, ¡use
el DOS!
¿Funciona Allegro bajo OpenDos?

Si, pero
con
problemas.
Si está
usando la
versión
OpenDOS
de
EMM386,
debe
desactivar
su
implement
ación
DPMI
(especifica
DPMI=OF
F en la
línea del
driver
EMM386.
EXE de tu
config.sys)
. También
debería
acordarse
de activar
la bandera
PIC=OFF,
pero ese es
el estado
por
defecto,
por lo que
no habría
problemas
con ello a
no ser que
lo haya
cambiado
antes.
¿Cómo puedo extender el limite de 256k de memoria de vídeo en Modo-X?
Tengo dos megas en mi tarjeta.

No puede.
El límite
está
impuesto
por el
hardware
de la VGA,
no por
Allegro.
Para
acceder a
más de
256k de
memoria
de vídeo
necesita
usar un
modo
SVGA, lo
cual
significa
cambiar a
una
resolución
mayor o
conseguir
una copia
del
programa
SciTech
Display
Doctor, el
cual provee
algunos
modos
SVGA de
baja
resolución.
¿Funciona la versión DOS de Allegro con la tarjeta de sonido SB-Live?
Para
algunas
personas si,
pero no
para otras.
El problema
es que
Creative
Labs se
niega a
revelar
información
interna
sobre la
tarjeta, por
lo que no
podemos
escribir un
driver para
ella.
Quéjese a
ellos, o
compre una
tarjeta de un
fabricante
diferente
más
razonable.
¿Por qué la versión DOS de Allegro reproduce los sonidos con menos
volumen que la versión Windows?

Esto puede
ser porque
tiene el
volúmen
muy bajo:
pruebe
modificarlo
desde el
programa
setup.
Además,
Allegro
mezcla
varios
sonidos en
un solo
buffer de
salida, a
diferencia
del
reproductor
de sonidos
de Windows
que sólo
reproduce un
sonido a la
vez, por lo
que cada
sonido
individual
sólo puede
obtener un
porcentaje
del volumen
total de
salida. Este
es el precio
que hay que
pagar por el
mezclado
múltiple de
canales. Si
no le gusta,
use el
programa
setup para
alterar el
número de
canales: el
número
puede ser
una potencia
de dos
menor o
igual a 64, y
cuanto
menor sea,
mayor será
el volúmen
del sonido.
Alternativa
mente, use
set_volume_
per_voice(),
tal y como
se describe
en la
documentaci
ón. Esto le
permite
ajustar el
volumen
general de la
salida de
sonido
digital de
Allegro.
¿Por qué no funciona con mi tarjeta de vídeo?
Pruebe usar
un driver
FreeBE/AF
(http://www.t
alula.demon.
co.uk/freebe/)
, o el
programa
comercial
SciTech
Display
Doctor
(http://www.s
citechsoft.co
m). Si sigue
sin funcionar,
publique una
descripción
de su
problema a la
lista de
correo de
Allegro,
junto con una
copia de la
salida que
producen los
programas
afinfo y
vesainfo.
¿Por que no usar algún tipo de sistema de enlazado dinámico?

La interfaz
VBE/AF ya
proporciona
eso para los
drivers de
vídeo:
compruebe el
proyecto
FreeBE/AF en
http://www.tal
ula.demon.co.
uk/freebe/.
Para cosas
más generales
como las
rutinas de
sonido,
VESA, y las
rutinas del
modo-X, esto
sería
terriblemente
difícil de
conseguir
debido a que
los drivers
dependen
mucho de las
rutinas de
ayuda del
núcleo de la
biblioteca. El
formato DXE
no es lo
suficientement
e flexible
como para
soportar esto,
y no quiero
que Allegro
dependa de
otros paquetes
de enlazado
dinámico.
¡Obtengo el error "out of environment space" al ejecutar fix.bat o
vcvars32.bat!
Bueno pues,
entonces
necesita
incrementar el
tamaño de su
entorno :-)
Puede hacer
esto alterando
la
configuración
de su sesión
DOS (haga
click en el
menú de
sistema y
seleccione
"propiedades"),
o en el
arranque de su
config.sys (ej:
añada
"shell=c:\comm
and.com
/e:8192").
Problemas en Windows
¡Obtengo multitud de errores de compilación con "LPDIRECTDRAWSURFACE2"!

Necesita
indicarle a su
compilador
dónde
encontrar los
ficheros de
cabecera y
librerías de
DirectX: ponga
las rutas de los
directorios
/include y /lib
del kit de
desarrollo
DirectX en la
ruta de su
compilador/enl
azador.
Alternativamen
te, si no quiere
modificar nada
de su
configuración,
puede copiar
directamente
esos ficheros
del kit de
desarrollo de
DirectX a los
directorios
correspondiente
s de su
compilador.
Obtengo cantidad de errores de compilación con
"DDEDM_STANDARDVGAMODES"!

Necesita
actualizarse a
una versión más
reciente del
SDK de
DirectX, como
mínimo versión
5, que puede
obtener de la
web del
desarrollador de
Microsoft.
¡Obtengo errores sobre una función WinMain() o main() que falta!

Necesita escribir
END_OF_MAIN(
) justo tras su
función main().
Allegro usa esto,
junto con algo de
magia del
preprocesador,
para convertir su
función main()
normal en un
punto de entrada
WinMain() al
estilo Windows.
¡Obtengo el error "out of environment space" cuando ejecuto fix.bat o
vcvars32.bat!

Oh bueno, entonces
necesita
incrementar el
tamaño de su
entorno :-) Puede
hacer esto
modificando los
parámetros de su
ventana DOS
(pinche en menú de
sistema y
seleccione
"propiedades"), o al
arrancar en su
fichero config.sys
(ej:
"shell=c:\command.
com /e:8192").
Probelmas Unix
¡Obtengo errores sobre un "_mangled_main_address" no definido!

Necesita escribir
END_OF_MAIN()
justo tras su función
main(). Allegro usa
esto, junto con algo
de magia del
preprocesador, para
obtener una copia
de sus parámetros
argv[] (los necesita
para varias cosas
internas).
¡Los errores de compilación aparecen demasiado rápido para que los
pueda leer!

Necesita redirigir
stderr a un fichero,
para poder verlo
luego. El métido para
hacer esto depende
del intérprete de
comandos: si está
usando un intérprete
al estilo Bourne,
como bash, pruebe
"make 2> logfile.txt".
Cuando intento usar DGA2, obtengo "resolution not supported", ¡pero el
servidor X realmente soporta esa resolución!

Hay dos posibles


razones: 1) DGA2
puede soportar
diferentes
resoluciones/profundida
des de color que X,
ejecute el programa
gfxinfo para saber qué
combinaciones puede
usar, 2) Puede tener una
instalación DGA2 con
fallos, lea la siguiente
pregunta.
Cuando intento usar DGA2, ¡la pantalla se pone negra y el PC se bloquea!

Probablemente esté usando


un servidor XFree86 con
una implementación DGA2
errónea, como la 4.0.3
(empaquetada con Red Hat
7.1 por ejemplo).
Actualizarse a la 4.1.0
probablemente solucionará
su problema. Puede
obtenerla de
ftp://ftp.xfree86.org/pub/X
Free86/4.1.0/binaries/ tras
seleccionar el directorio
apropiado para su
plataforma según indican
las instrucciones del
fichero Install.

Problemas generales
Estoy intentando compilar el programa grabber, ¡pero no funciona!

El grabber debe ser


enlazado con el código en
datedit.c. Pero no se
debería preocupar por
hacer esto a mano:
simplemente ejecute
"make" y eso recompilará
todo para usted.
Cuando compilo Allegro, el make falla con algo como `Error: operands
given don't match any known 386 instruction' o `Error: no such instruction
`maskmovq %mm3, %mm1''.

Necesita actualizar su versión


de GNU binutils. Lea
readme.txt para descubrir la
versión mínima requerida que
necesita.
¿Puedo usar Allegro con mi compilador <foobar>?

No a no ser que <foobar> esté


mencionado en readme.txt como una
de las plataformas soportadas. Usted
podría adaptar Allegro a ese
compilador, pero eso suele significar
mucho trabajo. Si <foobar> es un
compilador de 16 bits para DOS
como Borland C, puede olvidar
inmediatamente la idea :-)
¿Qué es eso de "Allegro WIP" que otras personas no dejan de mencionar?

WIP significa "work in progress" (versión


en desarrollo), y se refiere a los cambios
más recientes en Allegro desde la última
versión oficial. Las versiones WIP de
Allegro pueden obtenerse como parches de
la página web de Allegro
(http://alleg.sourceforge.net/), y
normalmente son bastante estables, aunque
no tan bien comprobadas como una versión
final.
Consequí el parche WIP, pero no lo puedo aplicar.

¿Tiene una copia de patch.exe? Si no, vaya a


conseguirla del mismo lugar que consiguió el resto de
djgpp: es una herramienta estándar de la distribución
del compilador. Si tiene el programa patch pero no
funciona correctamente, asegurese de que está
instalando el parche encima de la versión no
modificada de Allegro que esté intentando actualizar.
(esta normalmente es la versión oficial más reciente
antes de la WIP, pero compruebe el fichero de texto
que viene con la WIP para estar seguro).
Cuando ejecuto la demo, dice que no puede encontrar demo.dat.

Este fichero se distribuye por separado en las versiones WIP. Está en:
http://alleg.sourceforge.net/wip.es.html. (alldata.zip)

¿Cómo puedo dibujar diferentes imágenes el mismo tiempo? Cuando dibujo la


siguiente, ésta estropea la paleta de colores de la primera.

Por supuesto: ¡así es como funciona el hardware de video! Sólo puede haber una paleta de colores usada
en un mismo momento. O convierte sus imágenes para que usen la misma paleta o cambia a un modo
gráfico truecolor.

¿Cómo puedo convertir mis gráficos para que usen la misma paleta de 256
colores?
Busque en la página web de Allegro.cc (http://www.allegro.cc/) algunas utilidades, como por ejemplo FixPal y Smacker.

Mis colores siempre salen mal. ¿Cómo puedo hacer una paleta de grises con
256 tonos de gris?
El hardware de la VGA solo usa 6 b its p ara cad a co mpo n en te d el co lo r, lo qu e sig n ifica qu e lo s v alo res d e lo s co lo res ro jo , verd e y azu l v an d esd e 0 a 63 en la p aleta d e co lo res, sin lleg ar a 25 5. Esto le d a un p oten cial d e 2 ^1 8 = 26 21 44 co lo res d iferen tes o 64 ton o s d e g ris. Si necesitas más, pu ed e usar la fun ció n d e la VESA 0 x4 F0 8 para selecc io n ar u n an ch o d e DAC de 8 b its, p ero Alleg ro no sop orta esto d irectamen te, y no se si esto se po dría h acer en d iferen tes o rd en ad ores con h ard ware d iferen te.

¿Cómo es que en mi pantalla aparece un color en los bordes de mi monitor?

Cuando
está en
un
modo
de 256
colores,
la
tarjeta
VGA
muestra
el color
#0
alreded
or del
área de
visualiz
ación
(en
modos
truecol
or usa
el color
negro).
El color
desapar
ecerá
en
cuanto
cambie
la
entrada
#0 de
su
paleta
de
colores
para
que sea
negra.
¿Cómo puedo hacer un fundido de pantalla en un modo gráfico truecolor?

Con
gran
difficult
ad :-)
No
existe
un truco
tan
sencillo
como
alterar
la paleta
de
colores,
por lo
que
tendrá
que
redibuja
r la
pantalla
más
clara u
oscura.
Podría
dibujar
rectáng
ulos
negros
translúc
idos
sobre la
pantalla
para
oscurec
erla, o
usar
draw_lit
_sprite()
para
colorear
el
bitmap
mientra
s lo
copia a
la
pantalla
, pero
tenga la
certeza
que
estas
operaci
ones
son
costosas
y
requiere
n un PC
rápido.
He intentado usar fade_in() y fade_out() en modos truecolor pero no
ocurre bada. ¿Qué estoy haciendo mal?
fade_in(
)y
fade_out
() sólo
funciona
n en
modos
de 8-bits
con
paleta.
Uno de
los
modos
para
hacer un
fundido
de
bitmap
es
recorrer
todos
los
pixels y
cambiarl
os
individu
almente.
Una
alternati
va es
dibujar
muchos
recuadro
s negros
translúci
dos
sobre la
pantalla.
No
obstante
, estos
métodos
pueden
ser
lentos.
El
ejemplo
exxfade.
c
demuest
ra cómo
hacer
fundidos
entre
dos
bitmaps.
Puede
modific
arlo para
que
haga
fundidos
de/hacia
una
pantalla
negra.
Lea
también
la
pregunta
anterior.
¿Cómo puedo generar animaciones en formato FLI o FLC?
Mire en
la página
web de
Allegro
(http://al
leg.sourc
eforge.n
et/) y
busque
algunas
utilidade
s, como
por
ejemplo
DTA y
Smacker
.
¿Cómo puedo hacer partes de mis sprites transparentes en modos
truecolor? No entiendo la documentación cuando dice "rosa fucsia"...

En su
program
a de
dibujo
favorito,
busque
las barras
de
desplaza
miento
RGB y
arrastre
las barras
roja y
azul tan
alto
como
pueda
(normal
mente
hasta
255, pero
depende
de las
unidades
que use
el
software)
, y la
barra
verde a
cero.
Esto
creará
una
sombra
de rosa
fucsia, o
como
otras
personas
prefieren
llamarlo,
magenta.
¡No consigo que las rutinas de polígonos en 3D funcionen!

Recuerde
que las
posicione
s de los
vértices
son
almacena
das en
formato
de punto
fijo, debe
usar la
macro
itofix()
para
desplazar
sus
coordena
das 16
bits a la
izquierda.
¡No consigo que la función rotate_sprite() funcione!

Recuerde
que el
ángulo de
rotación
es
almacena
do en
formato
de punto
fijo, por
lo que
debe usar
la macro
itofix() o
desplazar
sus
coordenad
as 16 bits
a la
izquierda.
Por
ejemplo,
rotate_spr
ite(bmp,
spr, x, y,
itofix(32))
rotará el
gráfico 45
grados.
¡No consigo que el objecto GUI d_icon_proc() funcione!

Probablem
ente está
intentando
inicializar
la
estructura
de diálogo
con un
puntero a
su bitmap,
¿verdad?
Eso no
funcionará
porque el
diálogo es
creado en
tiempo de
compilaci
ón, pero el
bitmap es
cargado en
tiempo de
ejecución,
por lo que
el
compilado
r todavía
no sabe
dónde
estará
localizado.
Necesita
rellenar la
estructura
de diálogo
con un
puntero
nulo, y
entonces
copiar el
puntero
del bitmap
real en el
campo dp
como
parte de su
código de
inicializaci
ón, tras
haber
cargado el
bitmap en
la
memoria.
¿Debo usar bitmaps, sprites RLE o sprites compilados?

Depende
de lo que
esté
haciendo.
Si sus
imágenes
son
totalmente
opacas, no
habrá
ventaja al
usar un
sprite RLE,
y
probablem
ente será
más rápido
si usa la
función
blit(). Si su
gráfico
tiene áreas
transparent
es, un
sprite RLE
será casi
siempre
más rápido
y pequeño
que la
función
draw_sprit
e(). Los
sprites
compilados
son por
regla
general un
poco más
rápidos
que las
otras
funciones
para
imágenes
transparent
es y
bastante
más
rápidas
para
gráficos
opacos,
pero esto
puede
variar. Se
usan mejor
con sprites
pequeños
en
máquinas
antiguas en
modo-x, y
podrían ser
más lentos
que blit() si
los usas en
modos de
vídeo
SVGA en
un pentium
(el gran
tamaño de
los sprites
compilados
afecta
severament
e la
efectividad
del cache).
¿Cómo hago para que mi juego vaya a la misma velocidad en cualquier
ordenador?
Debe
asegurarse
que la
lógica de su
juego se
actualiza a
una
velocidad
constante,
pero se
salta el
refresco de
la pantalla
de vez en
cuando si el
ordenador
es muy
lento. Esto
puede
hacerse
instalando
un
temporizad
or que
incrementar
á una
variable
global a la
velocidad
de la lógica
de su juego,
eg:
volatile int speed_counter = 0;

void increment_speed_counter()
{
speed_counter++;
}

END_OF_FUNCTION(increment_speed_counter);

void play_the_game()
{
LOCK_VARIABLE(speed_counter);
LOCK_FUNCTION(increment_speed_counter);

install_int_ex(increment_speed_counter,
BPS_TO_TIMER(60));

while (!game_over) {
while (speed_counter > 0) {
update_game_logic();
speed_counter--;
}

update_display();
}
}

¿Cómo puedo capturar una pantalla de mi programa que usa Allegro?


Añada una
llamada a
save_bitmap
() en alguna
parte del
código. Lea
en la
documentaci
ón de
save_bitmap
() una
explicación
de uno de
los fallos
más
comunes al
usar la
función, y
un poco de
código
fuente.
¿Cómo puedo generar un número aleatorio?

Llame
srandom(tim
e(NULL)) al
principio de
su programa,
y entonces
use random()
%límite para
obtener un
número
pseudo-
aleatorio
entre 0 y
límite-1.
¿Por qué no hacer una versión "lite" de Allegro? No necesito ninguna de
las rutinas de sonido, matemáticas o GUI...
No hay
necesidad de
hacerlo. El
enlazador
sólo incluye
partes de la
biblioteca que
realmente usa,
por lo que si
no llama
ninguna de las
rutinas de
mapeado de
texturas o
reproducción
de FLICs,
éstas no se
añadirán a su
ejecutable.
Esto no
funciona
perfectamente
porque hay
mucho código
de Allegro
que usa tabla
de punteros a
funciones que
hacen que
rutinas
innecesarias
se enlacen
con tu código,
por lo que la
mayoría de
las funciones
de gráficos
serán
incluidas en
cada
ejecutable,
pero he
intentado
reducir esto al
mínimo. Mire
allegro.txt
para más
información
sobre
métodos
precisos para
quitar algunos
controladores
de gráficos y
sonido.
¿Añadirás alguna vez soporte para las tarjetas aceleradoras 3D?
No. Creo que
este tipo de
soporte
hardware sería
mucho más util
como parte de
un API 3D,
cosa que
Allegro no es
(y nunca será).
Si quiere
trabajar en
esto, la
biblioteca
MESA (una
implementació
n libre de
OpenGL) es en
mi opinión el
lugar a mirar.
¿Por qué no añadir una función de reproducción de MODs?

Ya existen
varias muy
buenas
actualmente,
por ejemplo el
paquete
JGMOD. Siga
los enlaces de la
página web de
Allegro.cc
(http://www.alle
gro.cc/). No se
le permite que
sugiera que
alguna de las
bibliotecas
existentes sea
incluída en
Allegro, porque
este tópico ha
sido discutido
hasta la muerte
en la lista de
correo y estoy
cansado de él.
¿Por qué no añadir soporte de red?

Eso sería un
montón de
trabajo, y no
tengo tiempo
para hacerlo. Hay
varios paquetes
de soporte de red
actualmente en
desarrollo o
flotando por la
red, y en mi
opinión este tipo
de código es más
útil como
biblioteca externa
que como parte
de Allegro.
¿Por qué no puedo leer ficheros GIF con Allegro?

Unisys tiene la
patente en el
algoritmo de
compresión LZW
que es usado en el
formato GIF.
Quiero que Allegro
sea totalmente
libre y sin
restricciones, lo
que significa que
no puedo incluir
ningún código que
haya que licenciar
o pagar por
derechos de autor.
Mi programa se bloquea todo el tiempo. ¿Puede ser debido a un fallo de
Allegro?

Quizás. Intente aislar


el fragmento de
código mas pequeño
que es capaz de
reproducir el
problema, y lo
mirare. Si puede
mandarme un
programa de 10
líneas, lo
solucionaré.
Probablemente
podría solucionar
uno de 100 líneas.
1000, y no tengo
ninguna oportunidad
:-)
¿Puedo usar Allegro en mi programa comercial?

Claro. Lea las


condiciones giftware
en readme.txt. No me
importa lo que haga
con él, yno hay
problemas con el uso
comercial.
¿Cuando se terminará Allegro? No puedo esperar...
¡Cuando este acabado!
Los ánimos son
bienvenidos, pero no
tengo fechas fijas de
lanzamiento y no voy a
hacer una para usted. Tan
pronto como este hecho,
será puesto al público.
¿Dónde puedo encontrar fuentes para usar con Allegro?

Grabber puede importarlas


directamente de ficheros .fnt
con formato GRX o BIOS, o
puede dibujarlas usted en una
imagen .pcx con cualquier
programa. Busque en la
página de Allegro una
utilidad (ttf2pcx) que
convierte fuentes Windows
TrueType a formato .pcx.
¿Dónde puedo encontrar un conjunto de samples de instrumentos para el
controlador DIGMID?

En la página web de Allegro


(http://alleg.sourceforge.net/) hay
algunos enlaces. Puede usar los
patches de la Gravis (formato
.pat), o ficheros SoundFont 2.0
(.sf2), pero éstos últimos deberán
ser convertidos a un fichero
patches.dat con la utilidad
pat2dat.
¿Cómo convierto la documentación en el formato de Ayuda de Windows?

Necesita la utilidad de conversión


makertf
(ftp://ftp.coast.net/Coast/win3/winhelp/
mkrtf104.zip), y el compilador de
Ayuda Windows
(ftp://ftp.microsoft.com/Softlib/MSLFI
LES/HC505.EXE). Cree un directorio
temporal, copie ahí el fichero allegro.txi
del directorio allegro/docs, y ejecute los
comandos "makertf --no-warn
allegro.txi -o allegro.rtf -J allegro.hpj"
seguido de "hcp allegro.hpj". El
segundo comando dará muchos errores,
pero pueden ser ignorados con
tranquilidad.
¿Cómo puedo imprimir la documentación?

El fichero allegro.rtf puede ser leído


directamente por Microsoft Word e impreso
desde ahí, pero debería pinchar con el botón
derecho y actualizar los cambos de la tabla de
contenido e índice para que primero sean
rellenados con datos correctos. Alternativamente
puede instalar el pack TeX y usar los programas
tex y dvips para contertir allegro.txi en formato
Postscript.
¿Dónde puedo encontrar ejemplos de código fuente de programas que usan
Allegro, bibliotecas adicionales y tutoriales?
Mire la página web de Allegro, http://alleg.sourceforge.net/. Si
tiene algo que añadir a esto, ¡por favor, mándeme la URL!
¿Por qué se considera buena práctica en programación el definir PI como
una constante en vez de usar el valor 3.141592 en mi código?

Es la forma mas simple de actualizar su programa, en caso de que haya que cambiar el
valor de PI. Esto también hará su programa más portable a otros compiladores que usen
otros valores de PI.

¿Por qué parece que vsync() no funciona?


Un número de tarjetas gráficas tienen versiones erróneas o incompletas de la implementación VESA, y a menudo la función vsync() no está
implementada. Para ver ejemplos de dibujado sin parpadeos, mire el código del juego demo, el cual usa varios métodos para dibujarse.

¿Por qué hacer una espera activa del array key no funciona? Por ejemplo,
"while (!key[KEY_ENTER]);" no funciona.
Si el código funciona sin optimizaciones, podría ser un fallo de su compilador. Puede intentar forzar al compilador a hacer lo que desea mediante el siguiente ejemplo:

while (!key[KEY_ENTER])
yield_timeslice();

En este caso, no obstante, sería mejor usar readkey() en su lugar. O considerar actualizar o desactualizar su compilador.

Todavía estoy confundido. ¿Dónde pueden ayudarme?

Mire
http://al
leg.sour
ceforge
.net/ma
illist.es.
html.
Qué hacer cuando su programa con Allegro
no funciona

Contenido
• Introducción
• Parte 1 - ¿quién es el culpable?
• Parte 2 - cuando Allegro falla
• Parte 3 - cuando su programa falla
• Parte 4 - lo que la gente no hace (pero debería)
• Parte 5 - pidiendo ayuda
• Parte 6 - aprenda de mis fallos
• Parte 7 - escribiendo su petición
• Parte 8 - un modelo de perfección
Introducción
Cuando las cosas van mal, a menudo parece buena idea pedir a otras personas ayuda.
Afortunadamente para las personas en esta situación, hay muchas personas (tanto
desarrolladores de Allegro como usuarios) que están dispuestas a responder preguntas de
este tipo, pero hay varias cosas que puede hacer para que este proceso sea más eficiente.
Este documento describe algunos pasos que debe tomar cuando tiene un problema con un
programa que use Allegro, sugiriendo modos de solucionar el problema usted mismo, y
enseñando trucos sobre cuándo y/o cómo pedir ayuda. El seguir estas reglas hará la vida
más sencilla para el que le ayude (porque toda la información relevante será presentada de
modo conciso y útil), y para el ayudado (porque así será más probable que reciba una
respuesta rápida y precisa).

Parte 1 - ¿quién es el culpable?


¿Es un problema de Allegro, o de su código? Para descubrirlo, pruebe ejecutar los
programas test de Allegro, en particular test.exe (si tiene problemas con los gráficos),
play.exe (problemas de sonido), y el contenido completo del directorio examples (para
cualquier cosa que vaya mal). Si no puede reproducir el problema con uno de éstos,
entonces probablemente es un fallo suyo, por lo que salte a la parte 3 más abajo.

Si el problema está relacionado con los modos gráficos del DOS, debería empezar por
conseguir una copia del programa Display Doctor de http://www.scitechsoft.com/. Si esto
soluciona el problema, significa con toda seguridad que su driver VESA original estaba
estropeado de alguna manera. No estoy interesado en leer mensajes sobre problemas de este
tipo: no hay nada que pueda hacer para corregirlos, por lo que me temo que su única opción
es conseguir un driver VESA mejor, ya sea solicitando al fabricante de su tarjeta que
solucione sus errores, comprando Display Doctor, o escribiendo un driver FreeBE/AF para
su tarjeta (mire en http://www.talula.demon.co.uk/freebe/).

Si el problema tiene que ver con los modos gráficos, debería conseguir una copia de
UniVBE de http://www.scitechsoft.com/. Si esto soluciona el problema, significa que su
driver VESA original estaba estropeado de alguna manera. No estoy interesado en oír
problemas de este tipo: no hay nada que pueda hacer para solucionarlos, me temo que su
única opción es conseguir un driver VESA mejor, obligando al fabricante de tu tarjeta a que
solucione los fallos, comprando UniVBE, o escribiendo un driver FreeBE/AF para su
tarjeta (mire en http://www.talula.demon.co.uk/freebe/).

Parte 2 - cuando Allegro falla


Si sigue creyendo que el problema es de Allegro, mande un mensaje con una descripción
sobre su sistema y el problema, indique la versión de Allegro y su plataforma, su
configuración de hardware, y una lista exacta de los programas que pueden reproducir su
problema (es importante saber qué programas no funcionan, y cuales sí, en caso de que
funcione alguno).

Si el problema está relacionado con modos gráficos del DOS, también debería mandar los
resultados producidos por los programas afinfo y vesainfo (la versión reducida es suficiente
a no ser que se le indique específicamente usar el parámetro -v: esos datos extra no son
necesarios normalmente). Pruebe ejecutar el programa test.exe con varios drivers de
Allegro (otros drivers nativos que crea puedan funcionar con su tarjeta, el driver VESA 1.x
y VESA 2.0), en varios modos de vídeo, y describa exáctamente qué resoluciones causan
problemas. Si es capaz de ejecutar los programas en resoluciones SVGA, ejecute test.exe
con la opción Autodetect e indique el texto completo que aparece en el medio de la
pantalla.

Si el problema está relacionado con el sistema de sonido del DOS, pruebe usar el programa
setup para configurar manualmente su tarjeta. Quizás tenga que introducir manualmente los
parámetros del hardware, y si se trata de una tarjeta clon de la SB, pruebe seleccionar una
versión anterior a la que está siendo autodetectada (SB Pro, SB 2.0, o SB 1.0). Si sigue sin
conseguir que funcione, su mensaje de ayuda debería incluir el nombre y descripción de los
drivers que estén siendo autodetectados (ésta información es mostrada por el programa
play.exe).

Parte 3 - cuando su programa falla


Cuando un programa djgpp falla, normalmente volcará el contenido de la pila que parecerá
algo como esto:

Exiting due to signal SIGSEGV


General Protection Fault at eip=00001eca
[corte]

Call frame traceback EIPs:


0x00001eca
0x00001590
0x00001aea
Esta información le indica exactamente dónde ocurrió el fallo. Para que estos datos tengan
sentido, debe compilar su programa con información de depurado (usando el parámetro -g),
y ejecutar "symify programa.exe" cuando esté viendo el contenido de la pila en pantalla.
Eso cambiará los datos a algo parecido a esto:
Call frame traceback EIPs:
0x00001eca _strcpy+14
0x00001590 _main+56, line 7 of t.c
0x00001aea ___crt1_startup+138
En este caso, puede ver que el bloqueo ocurrió en la función strcpy(), que fue llamada en la
línea 7 de la función main() del fichero fuente t.c. Ahora sólo tienes que ir a esa línea, mirar
lo que esté haciendo allí, y corregirlo :-)

Nota: si el bloqueo ocurre dentro de una función de Allegro, el mensaje de error puede no
ser muy útil. Cuando esto ocurra puede recompilar Allegro con información de depuración
(lea el fichero readme), y enlazar su programa con esta versión de la biblioteca de
funciones.

Nota 2: incluso cuando el traceback apunta a una función de Allegro, no significa que sea
fallo de una rutina de Allegro. Cualquier rutina fallará si le pasa parámetros inválidos, por
lo que a no ser que pueda duplicar el problema con uno de los programas de ejemplo de
Allegro, debería asumir que es un caso de error de operador y chequear dos veces qué
valores le está pasando a la función de Allegro.

Parte 4 - lo que la gente no hace (pero


debería)
Uno de los errores más comunes cometidos por los programadores es ignorar el valor de
retorno de una función que puede fallar. Tal error normalmente llevará a otros errores
inusuales e inesperados, convirtiendo la depuración en una pesadilla. Hay muchas
funciones dentro y fuera de Allegro que pueden funcionar o no dependiendo de las
circunstancias. Sin embargo le harán saber si funcionaron o no gracias a los valores de
retorno documentados.

Siempre que llame a una función que puede fallar (sobre todo set_gfx_mode(),
install_sound(), y cualquier cosa que carga datos del disco), es _esencial_ que chequee el
valor devuelto por la función, y actúe en consecuencia.

Otra herramienta importante comúnmente olvidada es usar las opciones que activan los
mensajes de aviso del compilador más estrictos (gcc usa -Wall), cuando compile su código.
Cualquier mensaje de aviso que de el compilador con ésta opción representará casi con toda
seguridad un error en su programa, y debería ser corregido antes de hacer nada. Si usa gcc,
un truco útil es compilar además con el parámetro -O, porque esto fuerza al compilador a
examinar las acciones del programa con más detalle, activando comprobaciones más útiles.
Sin embargo debería desactivar las optimizaciones mientras depura su programa. A pesar
de ofrecer mejores mensajes de aviso, posiblemente moleste más tarde a las herramientas
de depuración que vaya a usar.
Parte 5 - pidiendo ayuda
Bueno, así que ha probado todo lo descrito arriba y su programa sigue sin funcionar. No
tiene ni idea de qué hacer ahora, por lo que es tiempo de aventurarse en las entrañas de la
red, con la esperanza de encontrar algún hombre sabio, adivino u oráculo que tenga la
respuesta a su pregunta...

El mejor lugar donde puede preguntar es probablemente la lista de correo de Allegro: más
detalles en el fichero readme.txt. Sin embargo, recuerde que esta lista es específica de
Allegro. Los problemas relacionados con el lenguaje C o el compilador djgpp pertenecen a
otros forums (comp.lang.c y comp.os.msdos.djgpp respectivamente).

Tanto la lista de emails de Allegro como la de djgpp son archivadas, y puede ojear los
mensajes desde sus páginas web respectivas. Es muy probable que encuentre una solución a
su problema mirando las respuestas a preguntas previas, lo que le evitará hacer la pregunta.

Según la netiqueta usual, se asume que cuando hace una pregunta en cualquier forum de
Internet al menos ya ha consultado primero la documentación relevante, leyéndola por
completo. Si el problema que tiene merece ser planteado a cientos de personas para que lo
resuelvan, seguramente merecerá la pena tomarse unos minutos extra para solucionar el
problema usted mismo. Allegro está documentado extensivamente y se considera un
prerequisito para hacer una pregunta no sólo el haber leído la documentación, sino también
haber examinado los programas de ejemplo.

Parte 6 - aprenda de mis fallos


Qué no hacer, Primera Parte:

"Mi programa se bloquea. Por favor, dime porqué."


Si, a veces recibo preguntas como ésta :-) A pesar de años de práctica, todavía no soy capaz
de leer el pensamiento, por lo que es inútil este tipo de pregunta. Para conseguir ayuda con
un problema debe describirlo con suficiente detalle como para que otras personas lo
entiendan y puedan reproducirlo: esto normalmente significa mandar parte de su código.

Qué no hacer, Segunda Parte:

"Tengo un problema con mi programa. Junto con este


email mando un
fichero zip de 500k que contiene diez mil líneas de
código y todos los
gráficos y sonidos necesarios: ¿por favor, puedes
depurarlo y decirme
cual es el problema?"
Después de desperdiciar tiempo y facturas de teléfono para recibir un fichero tan grande, es
poco probable que nadie _quiera_ ayudarle, sin olvidar el tiempo que se necesitaría para
leer y entender tal enorme cantidad de información. Tiene que aislar una parte más pequeña
de código que demuestre el problema: cuanto más corto sea, más probable será que alguien
le ayude. Recuerde que está pidiendo a otros que le hagan un favor, por lo que es su
responsabilidad hacerles este proceso tan sencillo como pueda.

Parte 7 - escribiendo su petición


La cosa más importante es incluir código que puede ser compilado y comprobado por la
persona que lee su mensaje. No mande simplemente todo su programa: extraiga una sección
pequeña que incluya las líneas específicas que causan su problema, o reproduzca el
problema de forma más simple (a menudo descubrirá que puede encontrar el error usted
mismo al hacer una versión simplificada de su programa, por lo que es un buen ejercicio
que puede hacer). Este código debería ser un programa pequeño pero completo que puede
ser compilado y ejecutado, ya que es muy difícil depurar fragmentos incompletos de
código.

Es mejor incluir el código directamente en el texto de su email, porque a la gente le


resultará más sencillo leer esto que si tuviesen que extraer el código de un attachment.

Idealmente su ejemplo debería evitar el uso de gráficos externos y ficheros de datos. Está
bien incluir un pequeño zip (máx 2k) que contiene información, o si no puede hacerlo, de
una descripción de qué ficheros necesita (ej: "pon un fichero .pcx de 32x32 llamado
"tile.pcx" en el mismo directorio que el programa). Si no hay modo alguno de simplificar
las cosas, debería copiar su programa y sus datos a una página web, y entonces dar la URL
del fichero zip en su mensaje.

Debería decir que línea de comando gcc ha usado para crear el programa, y ésta debería
incluir el parámetro -Wall.

Describa qué es lo que intenta hacer el programa (puede no ser obvio instantáneamente para
otras personas), y también qué es lo que hace realmente cuando lo ejecuta. Normalmente no
hace falta indicar el traceback de su programa cuando se bloquea (otras personas pueden
duplicarlo por sí mismas siempre y cuando consigan compilar su código), pero debería
indicar si aparece este traceback, o se bloquea el programa, o si devuelve resultados
incorrectos (si es así, en qué difieren estos de los que esperaba). Es útil marcar su código
con comentarios para indicar a qué línea apunta el traceback del programa.

Otra información que pueda añadir puede ser útil. Lo más importante es una descripción
corta de su hardware, información relevante de sus controladores, y la versión de Allegro
que está usando (por favor no diga "WIP" a secas, sino la fecha exacta si está usando una
versión que no sea oficial).

Parte 8 - un modelo de perfección


Como referencia, aquí tiene un ejemplo de lo que yo consideraría un mensaje ideal:

Estoy teniendo algunos problemas al intentar usar modos


hicolor en mi
programa, a pesar de que estos modos funcionen bien con
los programas test
de Allegro. Estoy usando Allegro 3.0 con djgpp 2.02
(versión gcc 2.8.1) en
un p166, ejecutando el programa bajo win95 y usando el
driver VESA 2.0
incluido por defecto, descrito por el programa vesainfo
como "Matrox
Graphics Inc.".

Este programa debería seleccionar una resolución 640x480


de 16 bits,
dibujar un rectángulo azul cerca de la esquina superior
izquierda de la
pantalla, y entonces esperar la pulsación de una tecla
antes de salir,
pero simplemente recibo un General Protection Fault cuando
lo ejecuto.

Lo compilo usando "gcc -Wall t.c -o t.exe -lalleg", y no


obtengo ningún
mensaje de error.

--- corta aquí, t.c ---

#include <stdio.h>
#include <allegro.h>

void main()
{
BITMAP *bmp = screen;

install_keyboard();

if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0)


{
printf("Error seleccionando modo de vídeo\n");
return;
}

set_color_depth(16);
/* ¡ se bloquea cuando llama rectfill ! */
rectfill(bmp, 32, 32, 64, 64, 0x001F);

readkey();
}

Introducción
Una vez Allegro 4.0 sea lanzado, planeamos mantener compatibilidad a nivel de interfaz de
programación (API, Application Programming Interface) para el resto de las series 4.0.x.
Por ejemplo, eso significa que podrá compilar su programa escrito para la versión 4.0 con
la versión 4.0.23 o la 4.2.1 de la librería. No obstante, para corregir algunas inconsistencias
de la API 4.0, podríamos hacer excepciones a esta regla y romper la compatibilidad estricta
en algunos casos. Pero esto se garantiza que no ocurrirá en aquellas series donde el número
mayor y menor son fijos; en otras palabras, dos versiones que difieran una de la otra
únicamente por el (tercer) número de revisión serán compatibles a nivel de API.

Cambios entre las series 4.0.x y 4.1.x


• El parámetro 'aspect' de get_camera_matrix() y get_camera_matrix_f() es
estrictamente conforme con la documentación; en particular, poniéndolo a 1 obliga
a las funciones a que no escalen. Este no era el caso antes, porque las funciones
multiplicaban este valor por 4/3.
• Menús creados de un array DIALOG (usando d_menu_proc para el puntero proc)
ahora usan correctamente los campos w y h como tamaños mínimos para sus
dimensiones inclusivas (al igual que el resto de los elementos GUI). Antes,
dibujarían un borde fuera de esta dimensión (1 pixel que sobreescribiría otros
elementos GUI), y una 'sombra' adicional abajo a la derecha (2 pixels que
sobreescribirían otros elementos GUI).
• La variable 'retrace_count' y la función callback 'retrace_proc' respetarán la
velocidad de refresco de la pantalla (si es conocida) cuando el simulador de retrazo
no esté instalado. Este no era el caso antes, excepto bajo Windows.
• El valor por defecto de la variable de configuración del ratón 'emulate_three' se ha
cambiado a 'no' en todos los casos (incluso si tiene un ratón de sólo dos botones).
• El bit COLORCONV_KEEP_TRANS es ahora estrictamente conforme con la
documentación; Esto antes no era así, porque era ignorado cuando se cargaban
bitmaps desde ficheros de datos. fixup_datafile también fue modificado para
preservar la transparencia cuando se active este bit, lo cual no era garantizado
previamente en raras ocasiones.
• create_sub_bitmap() es ahora menos tolerante cuando recibe parámetros
incorrectos. Por ejemplo, compensaba los valores negativos del origen y devolvía
NULL si el bitmap padre era NULL. Estos casos ahora tienen aserciones en la
versión de depuración de la librería, pero no se comprueban en la versión
optimizada.
• install_allegro() y allegro_init() ahora devuelven un código de error si son incapaces
de iniciar el driver del sistema. Previamente simplemente abortarían la ejecución del
programa. Por consiguiente ahora debería verificar sus valores de retorno.

Introducción
Una vez Allegro 4.0 sea lanzado, planeamos mantener compatibilidad a nivel binario de la
interfaz (ABI, Application Binary Interface) para el resto de las series 4.0.x. Por ejemplo,
eso significa que seguirá pudiendo usar un binario compilado con la versión 4.0.10 con una
librería dinámica de la versión 4.0.42, o incluso 4.0.0.

"Uff," pensará, "nunca más tendré que poner allxxxx.dll en mis zips."

Técnicamente, no. Sin embargo, hay unas guías (reglas) que debería (deberá) seguir, o de lo
contrario las cosas no funcionarán bien, y obtendrá emails de irritación de sus usuarios y de
nosotros (la Mafia "sea bueno" de Allegro).

Nota: La compatibilidad binaria sólamente será mantenida _activamente_ para Windows,


Linux y BeOS en las arquitecturas x86.

Notas para Windows


Si no necesita una versión modificada de Allegro entonces simplemente enlace su programa
contra una versión que no sea WIP, CVS o de prueba, y caerán del cielo galletas de
chocolate. No desactive ninguna característica (ej: profundidades de color, drivers) en la
DLL.

Si requiere una versión modificada de Allegro, entonces por favor enlace con ella
estáticamente, o escoja un nombre no estándar para la DLL modificada de Allegro. Por
ejemplo, tendría muy mala leche si distribuyese la versión modificada de Allegro con un
nombre como all40.dll o alleg40.dll. En su lugar, llámela algo como alcambios.dll. Mejor
aún, enlace estáticamente con ella.

Para las personas que usen el Allegro estándar, proveeremos un conjunto de DLLs de
"referencia". Si su binario funciona con eso, entonces todo está en su lugar. Si quiere
distribuír las DLLs de Allegro con su programa (normalmente es buena idea),
recomendamos que distribuya nuestras DLLs en lugar de las que haya compilado usted.
Confiamos en que fastidiaría algo.
Notas para Linux
Para asegurarse de que el binario que use Allegro compilado en su máquina funcione en
otra, no desactive ninguna característica del `configure'. Su copia de Allegro debe tener
rutinas en ensamblador, threads, módulos, todas las profundidades de color y soporte X11
activados, entre otras cosas. Si duda, deje todo con su valor por defecto.

Cuando esté listo para distribuír su binario, ejecute "ldd <;mibinario>;". Debería decir algo
como:

liballeg.so.4.0 =>; /usr/local/lib/liballeg.so.4.0 (0xdeadbeaf)

NO debería decir algo como:

liballeg.so.4.0.0 =>; /usr/local/lib/liballeg.so.4.0.0 (0xdeadbeaf)

Si ve lo segundo, eso significa que usuarios con versiones posteriores de Allegro no podrán
ejecutar su binario.

Lea también la sección Windows si necesita usar una versión modificada de Allegro.

Notas para BeOS


La mayoría de las cosas mencionadas en la sección Windows son aplicables aquí. En
particular, se le recomienda usar una versión que no sea WIP, CVS o modificada de
cualquier otra forma, en cuyo caso su programa debería funcionar sin problemas en
máquinas externas.

Notas finales
Proporcionar el código fuente sigue siendo mejor que no proporcionarlo. Los binarios son
buenos, no obstante, si su código es malísimo y sólo usted (con la ayuda de brujería) es
capaz de compilarlo.

Si ha proporcionado binarios en el pasado usando versiones WIP de Allegro, le pedimos


amablemente que recompile su programa usando una versión estable de Allegro. (A no ser,
claro, que prefiera dormir con los peces).
Y oh, no haga que su compilador genere código específico de i686 o algo estúpido como
eso.

La Guía del Hacker de Allegro

Esta es una guía sobre ciertas partes internas de Allegro, para gente que esté interesada
en modificarlas. Este documento está lejos de ser completo, y puede no ser correcto al
100%. Recuerde que en caso de duda, el código fuente es siempre la referencia definitiva.
Serán bien aceptadas sugerencias sobre qué incluír en este documento: hay demasiado
código como para que pueda describirlo con todo lujo de detalles, por lo que quiero
concentrarme en las cosas que más confunden a la gente...

Contenido
• Estilo de código.
• Proceso de Construcción
• Ficheros de Cabecera
• Definiciones
• Soporte Unicode
• Rutinas de Ensamblador
• Otras Cosas

Estilo de código.
No voy a ser un fascista sobre esto, pero hace la vida más sencilla si todo el código usa un
formato consistente. Si va a escribir y mantener más de un fichero de código fuente
completo, creo que es libre para hacer lo que usted quiera, pero para pequeñas
contribuciones, posiblemente reformatearé su código para que encaje con mi estilo actual.
Obviamente me ahorrará tiempo si usted escribe el código con éste estilo, y aquí viene la
descripción:

Estilo Allegro básico: K&R, con 3 espacios de tabulado visual. Sin embargo, en disco los
tabuladores serán de 8 espacios, por lo que una línea que estuviese tabulada 12 espacios,
sería salvada en un fichero como 12 carácteres de espacio o 1 tabulador y 4 espacios, no 4
tabuladores. Si su editor de textos no puede entender la diferencia entre tabuladores
internos de 3 espacios y externos de 8 espacios, sería buena idea que consiguiese un editor
de textos mejor, o que usase el programa indent para conseguir este efecto. El fichero
indent.pro incluído con la distribución de Allegro casi consigue formatear el texto con este
estilo, pero no lo consigue siempre, y algunas cosas tienen que ser retocadas a mano.

Los defines de preprocesador y los nombres de las estructuras están EN_MAYUSCULAS.


Las funciones y las variables están en_minúsculas. Los NombresConMayúsculasMezcladas
son malvados y no deberían ser usados. Esa estúpida notación m_pHúngara es _realmente_
malvada, y ni si quiera debería pensar en ella.

Todos los símbolos deberían ser declarados como static, a no ser que sea imposible hacerlo,
en cuyo caso deberían ser prefijados con un subrayado.

Las funciones se verían así:

/* foobar:
* Descripción de lo que hace.
*/
void foobar(int foo, int bar)
{
/* hace algo útil */
}
Tres líneas en blanco entre funciones.

Los condiciones se verían así:

if (foo) {
/* cosas */
}
else {
/* cosas */
}
La única situación en la que algo está en la misma línea tras una llave de cerrado es el caso
de un bucle do/while, ejemplo:
do {
/* cosas */
} while (foo);
Los case se verían así:
switch (foo) {

case bar:
/* cosas */
break;

default:
/* cosas */
break;
}
Ejemplo de dónde poner espacios:
char *p;
if (condicion) { }
for (x=0; x<10; x++) { }
funcion(foo, bar);
(BITMAP *)data[id].dat;
Tódos los ficheros de código fuente deben empezar con la cabecera estándar:
/* ______ ___ ___
* /\ _ \ /\_ \ /\_ \
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/
__`\
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\
\
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\
\____/
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/
\/___/
* /\____/
* \_/__/
*
* Breve descripción de qué hace este fichero.
*
* Por Autor.
*
* Cosas chachis añadidas por Alguien Más.
*
* Fallo estúpido corregido por Tercera Persona.
*
* Lea en readme.txt la información de copyright.
*/
Los créditos de autor deben ser añadidos en orden cronológico, y las direcciones de email
no deben ser incluidas: esa información se puede encontrar en el fichero principal de
créditos, y si sólo existe en un lugar, es más fácil actualizarla cuando alguien cambie de
email.

Las personas sólo deben ser incluídas en la cabecera del código fuente si han hecho alguna
contribución significativa (las correcciones de una línea no cuentan), pero sin importar el
tamaño de la contribución, deben ser añadidos al fichero docs/thanks._tx. Este fichero es
ordenado alfabéticamente por nombre. Si la persona ya está en el fichero, hay que
actualizar el texto para describir el nuevo cambio, en caso contrario habrá que crear una
nueva entrada para el contribuyente. Además, cualquier cosa mayor que una modificación
minúscula debe ser añadida al fichero docs/changes._tx, que crece desde arriba en orden
cronológico inverso. Este fichero debe describir brevemente tanto la naturaleza de la
modificación como la persona que hizo esta modificación.

Proceso de Construcción
Esto es muy diferente dependiendo de si está usando autoconf o un makefile fijo. Sin
embargo, para la mayoría de las plataformas, el script de corrección (ej. fixdjgpp.bat),
creará un pequeño makefile, que define MAKEFILE_INC al make de otro fichero (ej.
makefile.dj), y entonces incluye makefile.all. Este contiene un montón de reglas genéricas,
e incluye el fichero nombrado en MAKEFILE_INC para proveer información adicional
específica de cada plataforma. Los ficheros fuente actuales están listados en el fichero
makefile.lst.

Hay tres versiones de la biblioteca de funciones: alleg (versión final), alld (depuración), y
allp (profiling). Los ficheros objeto van en obj/compilador/version/, donde versión es alleg,
alld, o allp. Los ficheros .lib van en lib/compilador/. Algunas cosas generadas (asmdefs.inc,
mmxtest.s, etc), van en el directorio raíz obj/compilador/. Las dependencias son generadas
con "make depend", y van en obj/compilador/version/makefile.dep, que es incluído por
makefile.all.

Cuando ejecuta "make clean", esto solamente borra los ficheros generados por el usuario,
como los ficheros objeto. "make distclean" le deja con la distribución original, e incluye
deshacerse de los ejecutables de test y la propia biblioteca de funciones. Para obtener la
máxima higiene personal, ejecute "make veryclean", lo que eliminará absolutamente todos
los ficheros generados. Tras esta operación, tendrá que ejecutar "make depend" para poder
reconstruir la biblioteca de funciones, y también "fixdll.bat" si está trabajando con la
plataforma Windows.

Para pasar líneas de comando largas a los enlazadores de MSVC y Watcom, el programa
runner.exe es compilado usando gcc, para que les pueda pasar un número decente de
parámetros. Este programa salva los parámetros en un fichero temporal, y entonces invoca
al programa usando el fichero con los argumentos como entrada.

Por ahora todos los makefiles usan gcc para generar las depependencias, porque es má fácil
que conseguir que MSVC o Watcom faciliten la información correcta.

El símbolo LIBRARY_VERSION, definido al comienzo de makefile.ver, es usado para


incluír el número de versión en cosas como el nombre de fichero de la DLL.

Ficheros de Cabecera
allegro.h vive en el directorio include/. Este incluye otros ficheros de cabecera que existen
en el árbol de subdirectorios include/allegro/. La razón de este método ligeramente extraño
es que allegro.h puede incluir cosas como "allegro/internal/alconfig.h", lo cual funcionará
tanto si compilamos Allegro, como si copiamos allegro.h al directorio include del sistema y
los otros ficheros de cabecera en include_sistema/allegro/. Esto evita inundar los directorios
de sistema con cientos de ficheros de cabecera, y a la vez permite a un programa incluir
solamente <allegro.h>, y hace posible el acceso a las cabeceras internas mediante #include
<allegro/include/aintern.h>.
allegro.h incluye alconfig.h, el cual detecta la plataforma actual e incluye un fichero de
cabecera adicional para este compilador (aldjgpp.h, almsvc.h, alwatcom.h, etc). Ese fichero
de cabecera adicional define un grupo de macros que describen el sistema, emula lo que sea
necesario para hacer que el código compile adecuadamente, y opcionalmente define
ALLEGRO_EXTRA_HEADER y ALLEGRO_INTERNAL_HEADER si va a necesitar
otros ficheros de cabecera específicos de la plataforma.

Tras incluir el fichero de cabecera de plataforma, el resto de alconfig.h define un montón de


macros genéricas de ayuda a sus valores por defecto, pero sólo si el fichero de cabecera de
plataforma no las ha sustituido por algo específico.

allegro.h contiene definiciones de estructuras y prototipos de funciones. Al final del


fichero, incluye alinline.h, el cual define todas las rutinas inline y los wrappers vtable, junto
con versiones en C de las rutinas matemáticas de punto fijo si no hay versión de éstas en
ensamblador en línea. Si el código de ensamblador en línea está soportado, incluye
al386gcc.h, al386vc.h, o al386wat.h.

Si ALLEGRO_EXTRA_HEADER está definido, allegro.h lo incluye al final. Este define


suele incluir aldos.h, alwin.h, etc, que definen cosas específicas para cada plataforma, como
valores ID para los drivers hardware. A diferencia de los ficheros de plataforma incluidos al
principio de allegro.h, éstos son específicos para cada SO en vez de para cada compilador,
por lo que el mismo fichero alwin.h puede ser usado tanto con MSVC como con
MinGW32. Describen funciones de la biblioteca relacionadas con la plataforma, mientras
los ficheros de cabecera previos describían la sintaxis básica del lenguaje.

aintern.h es como internal.h en versiones previas de Allegro, y define rutinas compartidas


entre múltiples ficheros de código fuente, pero que generalmente no queremos que sean
usadas por programas de usuario. Para definiciones internas específicas de cada plataforma
tenemos aintdos.h, aintwin.h, etc. Esto ficheros de cabecera no son incluidos directamente
por allegro.h, pero pueden ser incluidos por los programas de usuario valientes ó
estúpidos :-)

En plataformas que tienen rutinas API específicas y no portables, éstas deberían ir en un


fichero de cabecera especial en la raíz del directorio include, ej: winalleg.h. Este puede ser
incluido por programas de usuario que quieran acceder a estas rutinas, a la vez que se les
indica claramente que al incluir este fichero de cabecera están escribiendo código no
portable.

Definiciones
Todos los prototipos de funciones de cabecera deben usar la macro AL_FUNC(). Las
rutinas en línea usan la macro AL_INLINE(). Las variables globales usan AL_VAR() o
AL_ARRAY(). Los punteros globales a funciones usan AL_FUNCPTR(). Los punteros a
funciones que se pasan como parámetros a otras rutinas o que están almacenados en una
estructura usan AL_METHOD(). Esto puede parecer innecesario, pero da mucha
flexibilidad para añadir a una DLL especificadores de importación/exportación, marcadores
de convención de llamada como __cdecl, e incluso transformar los nombres de los símbolos
en algunos compiladores. Si olvida usar estas macros, su código no funcionará en algunas
plataformas.

Esto sólo es aplicable a ficheros de cabecera: puede escribir código C normal en el código
fuente.

El símbolo ALLEGRO_SRC es definido al compilar código fuente de la biblioteca. Si


quiere incluir una función en línea en su código fuente, use la macro INLINE. Para declarar
arrays de tamaño cero en una estructura, use int x[ZERO_SIZE]. Para usar enteros de 64
bits, declare la variable como LONG_LONG (esto no está definido en todas las
plataformas). Para realizar operaciones con nombres de ficheros, compruebe las macros
ALLEGRO_LFN, OTHER_PATH_SEPARATOR, y DEVICE_SEPARATOR. Lea los
ficheros de cabecera para ver los detalles.

Soporte Unicode
No asuma que las cadenas de caracteres son ASCII. No lo son. Si asume que si lo son, su
código puede funcionar mientras la gente que lo use esté tratando con datos UTF-8, pero
fallará horriblemente en cuanto alguien intente usarlo con cadenas Unicode de 16 bits, o
código GB Chino, o algún otro formato MIME extraño, etc. En cuanto vea un char * en
alguna parte, debe considerar que esto realmente contendrá el texto en el formato
actualmente seleccionado, por lo que debe ser extremadamente cuidadoso manipulando
cadenas de texto. ¡No lo olvide y nunca use una rutina libc con ellas!

Use las funciones Unicode para manipular todo el texto: lea los detalles en la
documentación. Cuando reserve memoria para su cadena, asuma que cada carácter ocupa
como mucho cuatro bytes: esto le dará espacio de sobra para los formatos de codificación
actuales.

Si quiere especificar una cadena constante, use la función uconvert_ascii("mi texto", buf)
para obtener una copia de "mi texto" en el formato de codificación actual. Si buf es NULL,
se usará un buffer interno estático, pero el texto convertido será sobreescrito por la
siguiente llamada a cualquier rutina de conversión de formato, por lo que no debería pasar
el texto a otras funciones de la biblioteca. Normalmente debería proveer usted el espacio de
conversión, reservando buf como un objeto temporal en la pila.

Para convertir en sentido contrario (ej. antes de pasar una cadena de texto de Allegro a una
rutina de SO que espera datos ASCII), llama a uconvert_toascii(mitexto, buf).
Para cualquier mensaje que pueda ser visto por el usuario, puede llamar
get_config_text("mi cadena ascii") en vez de uconvert_ascii(). Esto retornará un puntero a
memoria persistente (por lo que puede contar con la cadena indefinidamente), tras
convertirla al formato de codificación actual. Esta función es genial porque le evita la
molestia de reservar memoria para los datos convertidos, y porque permite que la cadena
sea reemplazada por las traducciones de language.dat. Debe tener la seguridad de pasar
siempre cadenas constantes a get_config_text(), en vez de texto generado o datos de otras
cadenas variables de texto: esto es para que el script findtext.sh pueda encontrar fácilmente
las cadenas que necesiten ser traducidas.

Los drivers de hardware deben inicializar su nombre y los campos desc a la cadena global
empty_string, y almacenar un nombre de driver ASCII en el campo ascii_name. El código
de soporte traducirá y convertirá automáticamente este valor, almacenando el resultado en
los campos name y desc. Para la mayoría de los drivers esto será suficiente, pero si desea
proporcionar una descripción más detallada, es problema de su driver ajustar ese dato desde
la rutina de inicialización, y encargarse de todas las conversiones necesarias.

Rutinas de Ensamblador
Los desplazamientos de estructuras están definidos en asmdef.inc, el cual es generado por
asmdef.c. Esto permite usar al código en ensamblador nombres legibles por un humano
para los miembros de una estructura, y ajustarlos automáticamente cuando se modifique la
estructura para añadir más valores, por lo que siempre siempre se ajustarán al formato
interno de las estructuras de C.

El código en ensamblador debe usar la macro FUNC(nombre) para declarar el comienzo de


una rutina, y GLOBL(nombre) cuando se quiera acceder a un símbolo externo (ejemplo:
una variable o función de C). Esto es para manejar las transformaciones de nombres de un
modo portable (COFF requiere un subrayado como prefijo, ELF no lo necesita).

Puede modificar %ds y %es en ensamblador, siempre y cuando recupere sus valores. Si
USE_FS y FSEG están definidos, también puede modificar %fs, de otro modo esto no es
requerido, y puede usar sin problemas el acceso con nearptr para todo.

No asuma que los códigos de operación MMX estén soportados: no todas las versiones de
ensamblador los conocen. Compruebe la macro ALLEGRO_MX, y sustituya su código
MMX en caso de que estas instrucciones no estén disponibles.

Otras Cosas
Cualquier rutina portable que se ejecute en un temporizador o una función callback de
entrada debe estar fijando (lock) todo el código y datos que toque. Esto se hace poniendo
END_OF_FUNCTION(x) o END_OF_STATIC_FUNCTION(x) tras toda definición de
función (no obstante, esto no es requerido si declara la función como INLINE), y llamando
a LOCK_FUNCTION() en alguna parte del código de inicialización. Use
LOCK_VARIABLE para fijar variables globales, y LOCK_DATA para fijar memoria
dinámica reservada.

Cualquier módulo que necesite código de desinicialización debería registrar una función de
salida llamando _add_exit_func(). Esto se asegurará de que todo se cierre grácilmente sin
importar si el usuario llama allegro_exit(), la función main() llega al final, o el programa
muere repentinamente debido a un error de ejecución. Debe llamar _remove_exit_func()
desde su rutina de desinicialización, o se encontrará atascado en un bucle infinito.

Parametros constantes en Allegro

Esto es un breve documento que le introducirá al uso de parámetros constantes con


Allegro. Detalla los cambios que ha sufrido el código interno de la librería, los cambios de
la API (principalmente transparentes) y lo que tendrá que hacer para adaptar su código
para que compile sin warnings del compilador (de nuevo, casi nada).

Contenido
• Cambios en la librería
• El define de preprocesador AL_CONST
• Cambios en la API de Allegro
• Funciones callback y punteros a punteros
• Objetos BITMAP
• Finalmente...

Cambios en la librería
Hay muy pocos cambios en el código de la propia librería; sólo algunas declaraciones y
definiciones han sido alteradas para incluír ALCONST. Lea debajo una descripción del
define de preprocesador AL_CONST. En algunos casos, alguna cadena era modificada
cuando no debía serlo - en estos casos, la cadena simplemente es duplicada y ésta copia es
eliminada al salir de la función.
Después de todo, ha habido pocos cambios al código de la librería.

El define de preprocesador AL_CONST


Para poder soportar compiladores que no conocen la palabra clave `const', o quizás usan
una palabra clave diferente, el símbolo de preprocesador AL_CONST es usado en lugar de
`const'. Note que en la documentación se usa `const' para que sea más legible.

Cambios en la API de Allegro


Estos son, generalmente, totalmente transparentes al usuario. No he cambiado el
comportamiento de ninguna función; únicamente los tipos de los parámetros. Básicamente,
si puede pasar a una función type* ptr, entonces puede pasar const type* ptr sin
ningún problema adicional. Note que algunos cambios pueden haber eliminado warnings
producidos por su programa debido a que las cadenas estáticas, etc, ahora son tratadas
como `const' por las funciones Allegro.

Hay algunos lugares, descritos a continuación, donde habrá un efecto en el código


existente.

La corrección del uso de `const' es realmente importante por dos razones. En primer lugar,
puede incrementar la legibilidad y comprensión de las funciones de Allegro (por ejemplo,
puede ver qué parámetros son alterados y cuales no). Segundo, le asegura que el código de
Allegro no está cambiando datos que no debería tocar, y que las funciones del cliente no
están corrompiendo Allegro modificando datos que no deberían tocar.

Funciones callback y punteros a punteros


Algunas funciones callback tienen ahora un tipo diferente - usan punteros `const' en lugar
de punteros no constantes. Por lo que se, un compilador puede mostrar mensajes de aviso
sobre tipos de punteros incompatibles. Debería actualizar sus funciones callback al nuevo
formato (que será documentado en el manual de Allegro).

Además, cuando pase un puntero a un puntero de una función de Allegro que está declarada
como recibiendo un AL_CONST type** ptr, deberá convertir su puntero a `const' si no lo
es ya. Por ejemplo:
int alguna_funcion_de_allegro(AL_CONST char** p);

void mi_funcion(char** x)
{
alguna_funcion_de_allegro((AL_CONST char**) x);
}
Me doy cuenta de que esto es un cambio a la API de Allegro, y que supuestamente hay que
evitar éstos a toda costa, pero esencialmente corrige un fallo en Allegro y a la vez modifica
el comportamiento. También asegura que la función callback proporcionada por el cliente
está funcionando correctamente, y no altera datos que no debería tocar. Las funciones
callback que no tratan los parámetros relevantes como constantes, son ligeramente erróneas
(pero potencialmente significantes).

Por favor note que para la función Unicode ugetx(), he proporcionado una versión
alternativa ugetxc(), que toma un parámetro `const char**' a diferencia del parámetro
`char**'. Esto es porque es válido pasar tanto un `char**' como un `const char**', pero
desafortunadamente no hay forma de decirle al compilador cuál queremos.

Objetos BITMAP
Allegro representa tanto la pantalla como un bitmap con un mismo objeto: un BITMAP.
Desafortunadamente, estas dos cosas pueden ser muy diferentes. Por ejemplo, leer un pixel
de un bitmap aparentemente no lo modifica, pero si estamos leyendo de una pantalla,
entonces es posible que deba ser alterado algún parámetro de la tarjeta de vídeo para
seleccionar la línea correcta, etc.

Por consiguiente, un parámetro const BITMAP no tiene sentido, y no se usa en ningún


punto de la librería. Esto es desafortunado, pero no veo ningún modo de solucionarlo.

Finalmente...
Sólo he probado esto con DJGPP 2.95.2, por lo que si tiene experiencias en las que esto no
funciona (he intentado que los ports Linux y BeOS funcionen correctamente, pero no puedo
garantizarlo...) mándame por email el mensaje de error *exacto* y lo arreglaré. También
puede contactar la lista de correo de desarrolladores de Allegro; lea la sección "Ayuda" del
manual de Allegro.

Email: lwithers@lwithers.demon.co.uk.

Gracias por escuchar :-)


Créditos de la traducción
Espero haberme acordado de todos los que deban ser mencionados aquí. Si su nombre no
está aquí, pido perdón, ¡y por favor, dígamelo para que pueda corregir mi fallo!

Traductores
Toni Ascó (e3445510@est.fib.upc.es).
Daniel Astillero (dastille@gyc.es).
Jesús García Carrero (i6791@fie.us.es).
Grzegorz Adam Hankiewicz (gradha@terra.es).
Alexander Ortiz de Guinea (bloowitt@mail.com).
Gabriel Szlechtman (szlechtman@hotmail.com).

¡Gracias!
Primero, muchas gracias a todos aquellos que han leído la traducción, y han expresado su
opinión sobre esta, mandando ya sea felicitaciones, críticas, correcciones, ánimos, etc.

Gracias a Shawn Hargreaves (shawn@talula.demon.co.uk) y a todo aquél que ha


contribuido algo a Allegro, una magnífica librería para hacer videojuegos.

Gracias a los chicos del proyecto LuCAS (http://lucas.hispalinux.es) por permitirnos usar
sus servidores para la página web, el servicio de cvs y por contribuir a la comunidad
hispanoablante con la mejor biblioteca en español dedicada a GNU/LiNUX.

Gracias por supuesto a todos los que contribuyen con el mundo del software libre, porque
tanto Allegro como Allegro-es existen gracias a ellos.

Conclusión
Todas las cosas buenas tienen un final. Escribir documentación no es algo bueno, y eso
significa que nunca se acaba la tarea. Siempre hay algo que he olvidado explicar, o algún
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/

You might also like