Saturday, December 9, 2017

INT 1Ch, Interrrupted

When a PC is running in real mode, there is a timer that fires an interrupt every 55 milliseconds. By default it does nothing, and gives control back to the system. A programmer can commandeer  this interrupt, and assign it to some kind of repeatable routine. As long as it hands control back to the system, everything is fine. Other minicomputers back in the day had some kind of mechanism like this. In the case of the Nintendo Entertainment System, the 6502 interrupt line was tied the the vsync of the TV. This fired every 16.66 milliseconds. Every time the system was ready to paint a new screen the interrupt would fire and you could do things like update the music, change the graphics, and other pseudo-mutitasking stuff.

Once again, Windows does not allow you to grab hardware interrupts. Allegro does have a timer service, but you have to check a queue to see of the timer has triggered. In a perfect world, your game would have input/update/render loop in step with the framerate. Here you could check the queue every loop and see if your timer fired and then do the things you need.  ROE doesn't have a loop like that. It's more a GUI that arbitrarily updates based on player input, not on framerate.When the timer fires in this game, everything is halted no matter what the game is doing and then the interrupt does all the game updating. After that it gives control back to the game. The game itself never knew the interrupt happened. As far is it's concerned a bunch of global variables were magically changed behind the scenes.

I was stuck. I couldn't use Allegro's queues to check for a timer because ROE doesn't have a mechanism to actively do that. It's all passive. I'm trying to change as little of the game code as possible for now. Ripping everything apart and writing a new program loop is not an attractive prospect on this pass. I want to keep my wanton destruction to the Nermal driver and maybe rarely insert or comment out a single line of code if it's in the main game.

My solution:  Threads to the rescue!.

Turns out Allegro has platform-independent thread services. Well, it requires that your OS offers pthreads, which is POSIX. In the case of Windows, Allegro will use it's thread service thingy just as well.

Inter-process communication will be handled the same way as the original game.. There are global interrupt flags that is read by the interrupt routine dictating how it was supposed to update things. My thread will just hang out, come to life every 55 milliseconds, check the flags and other globals, do it's thing and go to sleep. I will need a mechanism to kill the thread when the game is exited. I've discovered that if I kill my game before the thread, I'm stuck with a zombie process that's super hard to kill.

As much as I am having fun doing this. I'll be taking a day off tomorrow and probably just muse a bit on the blog here instead.

No comments:

Post a Comment