Hi, here's a small parser for archive files used by the Project: Starfighter game... The format is really not widely used :-) and the original game website has disappeared already; but writing this parser was good for training, and maybe you'd like to add it to Hachoir. You can also find the patch at https://bitbucket.org/oliver_g/hachoir/src/0f1b8b65dfac .
Also, a test file is attached, which is also used for the hachoir-parser test case. Thanks, Oliver
paktest.pak
Description: Binary data
# HG changeset patch # User Oliver Gerlich <oliver.gerl...@gmx.de> # Date 1319131489 -7200 # Branch prs-pak # Node ID 0f1b8b65dfac325de5d8bd7cee0a6cb12cb11dba # Parent b662b521c8b04b4347c1fa739f6bf05b6aaa616c add parser for PAK files from "Project: Starfighter" game diff -r b662b521c8b0 -r 0f1b8b65dfac hachoir-parser/hachoir_parser/archive/__init__.py --- a/hachoir-parser/hachoir_parser/archive/__init__.py Tue Sep 27 18:57:24 2011 +0200 +++ b/hachoir-parser/hachoir_parser/archive/__init__.py Thu Oct 20 19:24:49 2011 +0200 @@ -11,3 +11,4 @@ from hachoir_parser.archive.mar import MarFile from hachoir_parser.archive.mozilla_ar import MozillaArchive from hachoir_parser.archive.zlib import ZlibData +from hachoir_parser.archive.prs_pak import PRSPakFile diff -r b662b521c8b0 -r 0f1b8b65dfac hachoir-parser/hachoir_parser/archive/prs_pak.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hachoir-parser/hachoir_parser/archive/prs_pak.py Thu Oct 20 19:24:49 2011 +0200 @@ -0,0 +1,46 @@ +""" +Parallel Realities Starfighter .pak file parser + +See http://www.parallelrealities.co.uk/projects/starfighter.php +or svn://svn.debian.org/svn/pkg-games/packages/trunk/starfighter/ + +Author: Oliver Gerlich +""" + +from hachoir_parser import Parser +from hachoir_core.field import (ParserError, + UInt32, String, SubFile, FieldSet) +from hachoir_core.endian import LITTLE_ENDIAN +from hachoir_core.text_handler import filesizeHandler + +class FileEntry(FieldSet): + def createFields(self): + yield String(self, "filename", 56, truncate="\0") + yield filesizeHandler(UInt32(self, "size")) + yield SubFile(self, "data", self["size"].value, filename=self["filename"].value) + + def createDescription(self): + return self["filename"].value + +class PRSPakFile(Parser): + PARSER_TAGS = { + "id": "prs_pak", + "category": "archive", + "file_ext": ("pak",), + "mime": (u"application/octet-stream",), + "min_size": 4*8, # just the identifier + "magic": (('PACK', 0),), + "description": "Parallel Realities Starfighter .pak archive", + } + + endian = LITTLE_ENDIAN + + def validate(self): + return (self.stream.readBytes(0, 4) == 'PACK') + + def createFields(self): + yield String(self, "magic", 4) + + # all remaining data must be file entries: + while self.current_size < self._size: + yield FileEntry(self, "file[]") diff -r b662b521c8b0 -r 0f1b8b65dfac hachoir-parser/tests/download_testcase.py --- a/hachoir-parser/tests/download_testcase.py Tue Sep 27 18:57:24 2011 +0200 +++ b/hachoir-parser/tests/download_testcase.py Thu Oct 20 19:24:49 2011 +0200 @@ -90,6 +90,7 @@ (u"radpoor.doc", 103936, "114835a03be92e02029c74ece1162c3e"), (u"quicktime.mp4", 245779, "dc77a8de8c091c19d86df74280f6feb7"), (u"swat.blp", 55753, "a47a2d6ef61c9005c3f5faf1bca253af"), + (u"paktest.pak", 10464, "53ded116d139dbb172280f9e267ad3ed"), ) def stringMD5(text): diff -r b662b521c8b0 -r 0f1b8b65dfac hachoir-parser/tests/run_testcase.py --- a/hachoir-parser/tests/run_testcase.py Tue Sep 27 18:57:24 2011 +0200 +++ b/hachoir-parser/tests/run_testcase.py Thu Oct 20 19:24:49 2011 +0200 @@ -463,6 +463,13 @@ checkValue(parser, "jpeg_header_len", 10), ) +def checkPrsPak(parser): return ( + checkValue(parser, "/file[0]/filename", "hachoir/png_331x90x8_truncated.png"), + checkValue(parser, "/file[0]/size", 100), + checkValue(parser, "/file[1]/filename", "hachoir/small_text.tar"), + checkValue(parser, "/file[1]/size", 10240), +) + def checkFile(filename, check_parser): sys.stdout.write(" - Create parser: ") sys.stdout.flush() @@ -631,6 +638,7 @@ # radpoor.doc # quicktime.mp4 (u"swat.blp", checkSwat), + (u"paktest.pak", checkPrsPak), ) if __name__ == "__main__":