One of the features that is scheduled for the next version of MapTap (2.3) is the ability to play Opposing Force maps. This is a feature that we thought it was already working, until tests for 2.0 conducted with members from the Steam community pointed out that it wasn’t.
Phillip did a bit of research, called a guy (who knows a guy – just kidding; the person contacted by Phillip was the expert) who knows a bit more about this game, and it seems that Opposing Force is launched basically as a mod for Half-Life. This spells bad news for us, since MapTap would try to launch the proper game with the “-game” parameter, to specify the folder where we unpack the archives installed.
That expert however provided a solution: create .pak files with our contents!
That posed however some challenges. You see, I wanted to delegate this functionality to an external tool – we do this to extract the .7z archives, by the way. Something like calling an exe and specify the folder and the path to the .pak file to be created as command line parameters.
And that’s how the search started for .PAK file tools. It didn’t end well though: most of them were Windows applications, with no support for command line parameters. Don’t get me wrong, they are probably great tools, it’s just none was easy to interface with from MapTap.
Things turned for the better when finding the dirpack utility; apparently it was part of the QUtils package and then integrated with qcc. I already tried my hand with qcc and failed to convince it to produce a .pak file, so I took the bite, got the code for dirpack and started my attempts to compile it.
Let me tell you one thing: changing compiler specifications is bad. I bet that the code could produce executables, if you compiled it with an old enough compiler. But after an hour of hopelessly trying to put together a decent distribution of djgpp to compile it, I gave up on that approach and went on a different route: adapt the code to the current compilers.
My plan was to build it using CodeBlocks (it runs on MinGW), so the changes in the code went for that direction.
After fixing the obvious (renaming functions already available, finding the right headers to substitute some includes), I faced the first issue: ScanDir.
ScanDir is a function that returns the contents of a directory. You can even specify function pointers to do a bit of filtering and ordering. And it’s not provided for MinGW.
A look at the dirpack code however tells that these features were not used: the function was called with NULL for both function pointer parameters. This meant that even a crippled version of ScanDir would do the job, as long as it returns the complete list of files.
So, roll up the sleeves and start coding.
With that done, I was able to get the dirpack.exe compiled. Next step? Start testing. And see it failed.
Indeed, the .PAK file would not be created. Debugging the code, I found that file reading failed: the number of bytes returned by the read() call was not matching the size of the file. After horribly hacking the code, I finally got my first .PAK file. And surprise – surprise, when unpacking it the files were unusable.
Where could this error come from?
It turned out it was caused by the open() call. You see, a good time ago, all files were opened the same, regardless of their contents. There was no distinction made between text files and binary files. But then, as the open() function was ported to various platforms with their compilers, new rules were added to opening a file. Mainly, the O_BINARY flag, that specifies that for the file to be opened, all bytes from 0 to 255 are fair game.
With that flag in place, file operations ran fine. The .PAK files created could be extracted and the extracted content be used. Dirpack.exe rose from it’s ashes. MapTap support for Opposing Force is now possible.
I will release the code changes done for dirpack: who knows, somebody else might want to integrate it in their app.