install_int_ex(3)

πŸ“¦ version 4.4.3.1, in fedora 43, fedora 44

πŸ’– install_int_ex β€” the manual page, but make it cute πŸ’–

okay bestie, welcome to install_int_ex(3), straight out of the Allegro manual and into your group chat. this one is about timers and it's lowkey iconic. let's get into it 🫢


✨ NAME ✨

install_int_ex β€” adds or modifies a timer. it's part of the Allegro game programming library, and it's giving very much "make my code do things on a schedule" energy ✨


🌸 SYNOPSIS 🌸

#include <allegro.h>

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

like, that's the whole vibe. one function, two args, and suddenly you're a time lord πŸ‘‘


πŸ’… DESCRIPTION πŸ’…

so what does it actually DO? it adds a function to the list of user timer handlers. and if that function is already installed? it retroactively adjusts its speed β€” which means it acts as though the speed change happened precisely at the last tick. no cap. time-travel-adjacent behaviour, we love to see it πŸ•°οΈβœ¨

the speed you pass in is given in hardware clock ticks, and just so you know, there are 1193181 of those bad boys in a second. yeah. that many. she's specific πŸ’€

and because doing that math by hand is a crime, you can convert from other time formats to hardware clock ticks with these macros:

SECS_TO_TIMER(secs)  - give the number of seconds between
                       each tick
MSEC_TO_TIMER(msec)  - give the number of milliseconds
                       between ticks
BPS_TO_TIMER(bps)    - give the number of ticks each second
BPM_TO_TIMER(bpm)    - give the number of ticks per minute

slay, macros. doing the math so you don't have to πŸŽ€


now. the tea. there can only be sixteen timers in use at a time. sixteen!! that's it!! and some other parts of Allegro are already hogging them β€” specifically:

  • the GUI code
  • the mouse pointer display routines
  • rest()
  • the FLI player
  • the MIDI player

they all need to install handlers of their own, so bestie, pls don't go feral and use too many at the same time πŸ™ˆ

oh and also? if you call this routine without having first installed the timer module, install_timer() will be called automatically. she's self-sufficient. main character energy fr πŸ’…


🧚 how your handler actually gets called 🧚

your function will be called by the Allegro interrupt handler, not directly by the processor. so good news: it can be a normal C function and does not need a special wrapper πŸŽ‰

but now the serious part, and I mean it: it will be called in an interrupt context, and that imposes a LOT of restrictions on what you can do inside it. so:

  • it should not use large amounts of stack
  • it must not make any calls to the operating system
  • it must not use C library functions
  • it must not contain any floating point code
  • and it must execute very quickly

don't try to do lots of complicated code in a timer handler, okay? as a general rule you should just set some flags and respond to those later in your main control loop. tiny handler, big main loop. that's the formula 🫢


πŸ’€ the DOS protected mode warning (this one is scary) πŸ’€

in a DOS protected mode environment like DJGPP, memory is virtualised and can be swapped to disk. and due to the non-reentrancy of DOS, if a disk swap occurs inside an interrupt handler, the system will die a painful death. like, not metaphorically. actual painful death πŸ’€

so you need to make sure you lock all the memory β€” both code and data β€” that is touched inside timer routines. Allegro will lock everything it uses, but you are responsible for locking your handler functions. that's on you, bestie.

these macros exist to simplify that whole task:

  • LOCK_VARIABLE (variable)
  • END_OF_FUNCTION (function_name)
  • END_OF_STATIC_FUNCTION (function_name)
  • LOCK_FUNCTION (function_name)

for example, if you want an interrupt handler that increments a counter variable, you should write:

volatile int counter;

void my_timer_handler()
{
   counter++;
}

END_OF_FUNCTION(my_timer_handler)

and in your initialisation code you should lock the memory:

LOCK_VARIABLE(counter);
LOCK_FUNCTION(my_timer_handler);

obviously this can get awkward if you use complicated data structures and call other functions from within your handler, so you should try to keep your interrupt routines as simple as possible. simple handler = happy handler = happy you 🌸


⭐ RETURN VALUE ⭐

returns zero on success, or a negative number if there is no room to add a new user timer. so like, check it. she's telling you something πŸŽ€


🌈 SEE ALSO 🌈

go read these next, bestie, they're all connected:


and that's the whole page, bestie!! this one came from the Allegro manual, version 4.4.3, and it's filed under install_int_ex(3). go forth and schedule responsibly πŸ’–βœ¨πŸŽ€πŸ¦‹πŸ’…

πŸ“¦ where this page comes from