Basically, when you run the executable, the OS usually copies the program into memory (loading dynamic libraries when needed) and then every function call has an address which the program can get to (for example &fopen will get you the address of the fopen function).
There are 2 ways that you can then intercept library functions, especially ones which are part of the standard C libraries like fopen. The first is to simply wrap it:
FILE* MFOpen(const char* path, const char* mode)
{
// some crazy stuff here involving package loading/checking etc
...
else
{
return fopen(path, mode);
}
}
would do the job. The second is to replace the library function with some patching. Basically, when you start the program, you get the address of the original fopen call, replace it with a JMP instruction to your own code. It's usually used for things like debuggers as well as cracking programs where they replace authentication calls on other processes. For what our situation I think it would work quite well though as it would basically replace all calls to fopen in all libraries and route it through our package process, if needed.
Much as the Maratis code could easily be modified to use the first method, it would then also require changing TinyXML and any other libraries which don't have handy buffer loading. On the other hand, the function patching is a little more work, but then the buffer loading would probably be entirely redundant as DevIL almost definitely uses fopen internally, which would, again, be patched through to the custom function.
Having the pak-entity name as the relative path seems most logical. Agreed.
I don't know what the performance penalties might be, but it makes sense that accessing and potentially decrypting/decompressing larger amounts of data might be memory/cpu intensive. Also, usually there's no reason to keep things like frontend data in memory, so maybe worth trashing it on larger projects. Packages could then be mounted on top of each other... with the file loader looking first in the latest package loaded, then the previous one, then the previous one (etc) and falling back to the filesystem if no packages are loaded or the file isn't found in any of them.
Setting the password in C++ seems like a reasonable option, as you load any game plugin in the editor, I should be able to create something I can pull out during the publishing process.
I realise I sometimes have a tendency to over-engineer things. If you think that anything is wrong, or you'd prefer something done in a different way, just say. I chose to patch the function as it would more easily allow addition of libraries later to use the package management, but I don't want to seem like I'm trying to make design decisions on this. Maratis is your baby