[AD] Low-level Packfile Hooks

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Some two and a half years ago I committed a deadly sin. I used DJGPP's File System Extensions in Rock 'n' Spin, one of my games. These extensions allow the user to intercept file access at a very low level, certainly below Allegro's packfile structures, and I used them to apply a (probably not very) strong encryption algorithm to a file after the compression phase.

Now, 99% of Allegro users have had NT-based Windows, dodgy hardware, or both, forced on them, and my game is festering away in the mists of time (how's that for a mix of metaphors? :) until such a time as I can port it to Windows and Linux.

I propose, therefore, to write a low-level packfile hooking system. I won't be the only person to find this useful; someone who goes by the name of MikeDX on IRC EFnet #allegro wants to use functions like load_bitmap() and load_sample() (which use PACKFILEs) to load files from images in memory. The system I have in mind will require simple mechanical changes to src/file.c and some extra code to be written.

The PACKFILE system (see src/file.c) is built on top of several functions from unistd.h, including open(), close(), dup(), lseek(), read() and write(). These functions operate on file descriptors (ints typically named fd). The only platform that has special-case handling is the Mac, for which src/mac/mfile.c provides a wrapper to open() and the other unistd.h functions are used as normal. The wrapper seems only to translate the filename into a Mac-formatted path.

My changes would have the existing PACKFILE system operating on virtual file descriptors. Each virtual file descriptor would have a set of hook functions associated with it, and these would be called instead of the above lseek(), read(), etc. The parameters would be the same in each case (except that the fd would be virtual). dup() wouldn't be hooked, but would be replaced with a special version that works on virtual fd's; the underlying dup() wouldn't actually be needed, but this is unimportant.

open() is a special case, since it has to generate an fd rather than take one. The user would add a series of 'open hooks'. Any calls to open() would be replaced with an algorithm that calls the open() hooks in turn, giving each the opportunity to hook the new fd (the most recently registered hook has first refusal). If no hook accepts the new fd, a default hook is installed; this default hook chains to the underlying open() implementation.

When an open hook takes control of an fd, it can allocate memory and call a function to store a void * pointer with the fd. Then the other functions can request the void * pointer by calling another function. The close() hook is then responsible for freeing it. However, it is not necessary to use the void * pointer.

If an open hook needs to open a file of its own, it can call a special Allegro function. This function will defer to _al_open() on the Mac or open() on other systems.

Before I go ahead and code this, I have a few questions:

Will the changes be accepted? I'll test it myself, especially making sure that the existing packfile functionality isn't crippled.

How portable are these unistd functions? DJGPP's libc docs list them as POSIX, which means MSVC might be obfuscating the function names for no reason - but at first sight I couldn't find any preprocessor magic in Allegro's headers to get around such a problem. I don't have MSVC myself. Can anyone confirm what the situation is?

Any other suggestions of ways to improve the system (without making me do a lot more work :)?



MSN Photos is the easiest way to share and print your photos: http://photos.msn.com/support/worldwide.aspx

Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/