04 Rutinas de temporizaci�n

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.

Volver al Indice