Author: fabian-guest
Date: 2012-10-04 10:54:19 +0000 (Thu, 04 Oct 2012)
New Revision: 13793

Added:
   packages/trunk/funguloids/debian/mpak.py
Modified:
   packages/trunk/funguloids/debian/control
   packages/trunk/funguloids/debian/copyright
   packages/trunk/funguloids/debian/rules
Log:
Add MPAK package handling utility from upstream, licensed under the MIT 
license, to fix broken data packages during package building.

Modified: packages/trunk/funguloids/debian/control
===================================================================
--- packages/trunk/funguloids/debian/control    2012-10-04 10:50:15 UTC (rev 
13792)
+++ packages/trunk/funguloids/debian/control    2012-10-04 10:54:19 UTC (rev 
13793)
@@ -13,7 +13,8 @@
  libopenal-dev,
  libogg-dev,
  libvorbis-dev,
- libmad0-dev
+ libmad0-dev,
+ python
 Standards-Version: 3.8.3
 Vcs-Svn: svn://svn.debian.org/svn/pkg-games/packages/trunk/funguloids/
 Vcs-Browser: 
http://svn.debian.org/wsvn/pkg-games/packages/trunk/funguloids/?op=log

Modified: packages/trunk/funguloids/debian/copyright
===================================================================
--- packages/trunk/funguloids/debian/copyright  2012-10-04 10:50:15 UTC (rev 
13792)
+++ packages/trunk/funguloids/debian/copyright  2012-10-04 10:54:19 UTC (rev 
13793)
@@ -45,3 +45,27 @@
 
 The Debian packaging is Copyright 2007, Andres Mejia <[email protected]> and
 is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
+
+Copyright and License for debian/mpak.py:
+
+       MPAK package handling utility
+       Version 1.5 (Python-implementation)
+       Copyright (c) 2008, 2012, Mika Halttunen. <http://www.mhgames.org>
+
+       Permission is hereby granted, free of charge, to any person obtaining a
+       copy of this software and associated documentation files (the 
"Software"),
+       to deal in the Software without restriction, including without 
limitation
+       the rights to use, copy, modify, merge, publish, distribute, sublicense,
+       and/or sell copies of the Software, and to permit persons to whom the
+       Software is furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included 
in
+       all copies or substantial portions of the Software.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
THE
+       AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+       LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+       FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+       DEALINGS IN THE SOFTWARE.

Added: packages/trunk/funguloids/debian/mpak.py
===================================================================
--- packages/trunk/funguloids/debian/mpak.py                            (rev 0)
+++ packages/trunk/funguloids/debian/mpak.py    2012-10-04 10:54:19 UTC (rev 
13793)
@@ -0,0 +1,376 @@
+#!/usr/bin/python
+"""
+       MPAK package handling utility
+       Version 1.5 (Python-implementation)
+       Copyright (c) 2008, 2012, Mika Halttunen. <http://www.mhgames.org>
+
+       Permission is hereby granted, free of charge, to any person obtaining a
+       copy of this software and associated documentation files (the 
"Software"),
+       to deal in the Software without restriction, including without 
limitation
+       the rights to use, copy, modify, merge, publish, distribute, sublicense,
+       and/or sell copies of the Software, and to permit persons to whom the
+       Software is furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included 
in
+       all copies or substantial portions of the Software.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
OR
+       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
THE
+       AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+       LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+       FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+       DEALINGS IN THE SOFTWARE.
+       
+       - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
-
+       Description follows:
+       
+       This command line tool allows creation and extraction of MPAK (.mpk) 
packages used
+       in several of my games. MPAK is a simple WAD-like file format of mine, 
that allows storing
+       the game data in one single .mpk file. I originally had a very crude 
command line program
+       bit like this one (written in C++), and decided to write this 
Python-implementation as
+       an Python-programming excercise. So, it's my first Python program. :)
+
+       Version history:
+       v1.5: Licensed under MIT license (no functional changes)
+       v1.4: The first Python version
+       v1.0 -- v1.31: The original C++ implementation
+"""
+import getopt, sys
+import os
+import traceback
+import struct
+import binascii
+import fnmatch
+import shutil
+from ctypes import c_uint32
+
+def usage():
+       """
+       Prints the program usage.
+       """
+       print "MPAK package handling utility"
+       print "Version 1.5 (Python-implementation)"
+       print "Copyright (c) 2008, 2012, Mika Halttunen."
+       print ""
+       print "Usage:", sys.argv[0],"[switch]","-f 
pakfile.mpk","[file1]","[file2]", "[...]", "[fileN]"
+       print "where [switch] is one of the following:"
+       print "  -f, --file=FILE   Use package FILE"
+       print "  -c, --create      Create a new package with files 'file1' to 
'fileN'"
+       print "  -l, --list        List the files from given package"
+       print "  -e, --extract     Extract all files (by default) from given 
package. If you"
+       print "                    want to only extract some specific files, 
you can name"
+       print "                    them individually, and/or use wildcards 
(i.e. *.png)."
+       print "                    You can supply path where to extract with 
-p."
+       print "  -p, --path=PATH   Extract to PATH (created if doesn't exist)"
+       print "  -h, --help        Print this usage text"
+       print ""
+
+
+def errorMsg(msg):
+       """
+       Prints an error message and exits.
+       """
+       try:
+               pos = traceback.extract_stack(limit=2)
+               if pos:
+                       print "ERROR: In %s:%s, line %d:" % (pos[0][0], 
pos[0][2], pos[0][1])
+               else: print "ERROR:"
+               print "\t",msg
+       except:
+               if __debug__:
+                       traceback.print_exc()
+               pass
+       sys.exit(2)
+
+
+def separator():
+       """
+       Prints the separator line.
+       """
+       print "-"*75
+
+
+def computeCRC(file, offset):
+       """
+       Computes the CRC32 for the file, starting at given offset.
+       """
+       f = open(file, "rb")
+       f.seek(offset)
+       crc = 0
+
+       # Compute a running CRC32 for the file in 16kb chunks
+       while True:
+               buffer = f.read(16384)
+               if buffer == "": break          # End of file
+
+               crc = binascii.crc32(buffer, crc)
+
+       f.close()
+       return crc
+
+
+def createPackage(pakFile, files):
+       """
+       Creates a new MPAK package.
+
+       This copies the given files into the new package file, writes the file 
table
+       and closes the package. MPAK doesn't support adding new files to an 
existing
+       package.
+       """
+       print "Creating '%s'.." % pakFile
+       if len(files) < 1: errorMsg("No input files specified!")
+       separator()
+
+       # Open the package file for writing
+       out = open(pakFile, "wb")
+
+       # Write the header and reserve 4+4 bytes for CRC32 and file table offset
+       out.write("MPK1")
+       out.write("."*8)
+
+       # Write each file
+       package = { "fileNames": [], "fileOffsets": [] }
+       count = 0
+       for file in files:
+               # Get the basename
+               filename = os.path.basename(file)
+               print " <",filename,"...",
+               package["fileNames"].append(filename)
+
+               # Get the file size in bytes
+               stats = os.stat(file)
+
+               # Store the current offset
+               package["fileOffsets"].append(out.tell())
+
+               # Open the file and copy its contents
+               f = open(file, "rb")
+               shutil.copyfileobj(f, out, 16384)
+               f.close()
+
+               print "OK. (%.1f KB)" % (stats.st_size / 1024.0)
+               count = count + 1
+
+       separator()
+
+       # Grab the file table offset and write the table
+       ftOffset = out.tell()
+
+       # Write the number of files
+       out.write(struct.pack("<L", count))
+
+       # Write the file information
+       for i in range(count):
+               # File name length
+               length = len(package["fileNames"][i]) + 1
+               out.write(struct.pack("B", length))
+               # File name, plus one zero for the C++ implementation
+               out.write(package["fileNames"][i])
+               out.write(struct.pack("B", 0))
+               # File offset
+               out.write(struct.pack("<L", package["fileOffsets"][i]))
+
+       # Update the header to have the correct file table offset
+       out.seek(8)
+       out.write(struct.pack("<L", ftOffset))
+
+       # Compute the CRC32 and write it to the header
+       out.flush()
+       crc32 = c_uint32(0)
+       crc32.value = computeCRC(pakFile, 8)
+       out.seek(4)
+       out.write(struct.pack("<L", crc32.value))
+
+       print "Added %d files to %s" % (count, pakFile)
+       print "Package '%s' created successfully. CRC32 checksum is %s." % 
(pakFile, hex(crc32.value))
+       out.close()
+
+
+def readPackage(pakFile):
+       """
+       Opens the given MPAK package, reads its information and stores it to a
+       package dictionary. Returns the dictionary.
+       """
+       packageInfo = { "filename": pakFile }
+
+       f = open(pakFile, 'rb')
+       if f.read(4) != "MPK1": errorMsg("Unsupported file format!")
+
+       # Read the CRC32 checksum and the file table header offset
+       buffer = f.read(8)
+       crc32, headerOffset = struct.unpack("<LL", buffer)
+       crc32 = int(crc32)
+       packageInfo["crc"] = crc32
+
+       # Check that the CRC32 matches
+       checksum = c_uint32(0)
+       checksum.value = computeCRC(pakFile, 8)
+       if checksum.value != crc32:
+               f.close()
+               errorMsg("Checksum doesn't match; perhaps a corrupted package?")
+
+       # Seek to the file table, and read the number of files
+       f.seek(headerOffset)
+       numFiles = struct.unpack("<L", f.read(4))[0]
+       packageInfo["numFiles"] = numFiles
+
+       # Read the file information
+       fileNames = []
+       fileOffsets = []
+       for i in range(numFiles):
+               namelen = struct.unpack("B", f.read(1))[0]
+               file = f.read(namelen)
+               offset = struct.unpack("<L", f.read(4))[0]
+               fileNames.append(file[:-1])             # Remove the trailing 
null character
+               fileOffsets.append(offset)
+
+       # Compute the file sizes from the offsets
+       fileSizes = []
+       for i in range(numFiles-1):
+               fileSizes.append(fileOffsets[i+1] - fileOffsets[i])
+       fileSizes.append(headerOffset - fileOffsets[numFiles-1])
+
+       # Store the information
+       packageInfo["fileNames"] = fileNames
+       packageInfo["fileOffsets"] = fileOffsets
+       packageInfo["fileSizes"] = fileSizes
+       f.close()
+       return packageInfo
+
+
+def listPackage(pakFile):
+       """
+       Lists the contents of a MPAK package.
+       """
+       print "Listing '%s'.." % pakFile
+       package = readPackage(pakFile)
+
+       # Print the listing
+       numFiles = package["numFiles"]
+       print "'%s' (CRC32: %s) contains %d files:" % (pakFile, 
hex(package["crc"]), numFiles)
+       print ""
+       print " NUM : FILE                           : SIZE(KB)   : OFFSET"
+       separator()
+       for i in range(numFiles):
+               print " %3d : %30s : %-10.1f : (at %s)" % (i+1, 
package["fileNames"][i], package["fileSizes"][i] / 1024.0, 
hex(package["fileOffsets"][i]))
+
+       separator()
+       print " NUM : FILE                           : SIZE(KB)   : OFFSET"
+
+
+def extractPackage(pakFile, path, filters):
+       """
+       Extracts files from a package to given path.
+
+       By default extracts all the files. Can be given list of wildcards (i.e. 
*.png) to
+       extract only the files that match given wildcards. Wildcards can also 
be file names
+       from the package.
+
+       The given path is created if it doesn't exist.
+       If the path is just a single directory name, it's assumed to exist in 
the current
+       working directory.
+       """
+       print "Extracting files from '%s' to %s.." % (pakFile, path)
+       package = readPackage(pakFile)
+
+       # Try to create the path if it doesn't exist
+       path = os.path.abspath(path)
+       if not os.path.exists(path):
+               print "Path",path,"doesn't exist, creating it.."
+               try:
+                       os.makedirs(path)
+               except:
+                       errorMsg("Unable to create directory " + path + "!");
+
+       separator()
+
+       # Open the file, and extract all the individual files from it
+       count = 0
+       f = open(pakFile, "rb")
+       for i in range(package["numFiles"]):
+               # Test if the file name matches the given wildcard
+               if len(filters) > 0:
+                       for filter in filters:
+                               if fnmatch.fnmatch(package["fileNames"][i], 
filter):
+                                       break
+                       else: continue
+
+               print " >", package["fileNames"][i],"...",
+               # Seek to the correct offset
+               f.seek(package["fileOffsets"][i])
+
+               # Open a new file for writing, and write the file out in 16kb 
chunks
+               out = open(os.path.join(path, package["fileNames"][i]), "wb")
+               bytesWritten = 0
+               bytesTotal = package["fileSizes"][i];
+               while True:
+                       # We have to watch not to write too much
+                       bytesLeft = bytesTotal - bytesWritten
+                       if bytesLeft > 16384: bytesLeft = 16384
+
+                       buffer = f.read(bytesLeft)
+                       out.write(buffer)
+                       bytesWritten = bytesWritten + bytesLeft
+
+                       if bytesWritten == bytesTotal:
+                               break
+
+               out.close()
+               print "OK."
+               count = count + 1
+
+       f.close()
+       separator()
+       print "%d (of %d) files extracted to %s." % (count, 
package["numFiles"], path)
+
+
+def main():
+       """
+       Main method.
+       """
+       try:
+               # Get the optiosn
+               opts, args = getopt.getopt(sys.argv[1:], "f:clep:h", ["file=", 
"create", "list", "extract", "path=", "help"])
+       except getopt.GetoptError, err:
+               # Print the program usage and exit
+               print "ERROR:", str(err)
+               usage()
+               sys.exit(2)
+
+       extractPath = os.getcwd()
+       pakFile = None
+       action = None
+
+       # Handle the options
+       for o, a in opts:
+               if o in ("-f", "--file"):
+                       pakFile = a                                     # Grab 
the pakfile
+               elif o in ("-c", "--create"):
+                       action = "create"
+               elif o in ("-l", "--list"):
+                       action = "list"
+               elif o in ("-e", "--extract"):
+                       action = "extract"
+               elif o in ("-p", "--path"):
+                       extractPath = a                         # Grab the path
+               elif o in ("-h", "--help"):
+                       usage()
+                       sys.exit()
+               else:
+                       assert False, "Unhandled option"
+
+       # Check that we got a pakfile
+       if pakFile == None:
+               usage()
+               sys.exit(2)
+
+       if action == "create": createPackage(pakFile, args)
+       elif action == "list": listPackage(pakFile)
+       elif action == "extract": extractPackage(pakFile, extractPath, args)
+       else: usage()
+       sys.exit()
+
+if __name__ == "__main__":
+       main()
+


Property changes on: packages/trunk/funguloids/debian/mpak.py
___________________________________________________________________
Added: svn:executable
   + *

Modified: packages/trunk/funguloids/debian/rules
===================================================================
--- packages/trunk/funguloids/debian/rules      2012-10-04 10:50:15 UTC (rev 
13792)
+++ packages/trunk/funguloids/debian/rules      2012-10-04 10:54:19 UTC (rev 
13793)
@@ -10,6 +10,35 @@
 
 override_dh_auto_configure:
        CXXFLAGS="$(CXXFLAGS)" dh_auto_configure -- --with-fmod=no
+       
+       chmod +x debian/mpak.py
+       
+       if test ! -e bin/bootstrap.mpk.orig ; then \
+               cp bin/bootstrap.mpk bin/bootstrap.mpk.orig ; \
+               ./debian/mpak.py -e -f bin/bootstrap.mpk  -p _bootstrap ; \
+               sed -ri '/^[A-Z]/ s/(.*)/overlay \1/' _bootstrap/*.overlay ; \
+               ./debian/mpak.py -c -f bin/bootstrap.mpk  _bootstrap/* ; \
+               rm -rf _bootstrap ; \
+       fi
+       
+       if test ! -e bin/funguloids.mpk.orig ; then \
+               cp bin/funguloids.mpk bin/funguloids.mpk.orig ; \
+               ./debian/mpak.py -e -f bin/funguloids.mpk -p _gamedata ; \
+               sed -ri '/^[A-Z]/ s/(.*)/overlay \1/' _gamedata/*.overlay ; \
+               sed -ri '/^[A-Z]/ s/(.*)/particle_system \1/' 
_gamedata/*.particle ; \
+               sed -ri 's/^(\t\t\t)(texture_unit) 1/\1\2\n\1{\n\1}\n\1\2/' 
_gamedata/materials.material ; \
+               ./debian/mpak.py -c -f bin/funguloids.mpk _gamedata/* ; \
+               rm -rf _gamedata ; \
+       fi
 
 override_dh_auto_clean:
        dh_auto_clean -- clean distclean
+       
+       if test -e bin/bootstrap.mpk.orig ; then \
+               mv bin/bootstrap.mpk.orig bin/bootstrap.mpk ; \
+       fi
+       
+       if test -e bin/funguloids.mpk.orig ; then \
+               mv bin/funguloids.mpk.orig bin/funguloids.mpk ; \
+       fi
+


_______________________________________________
Pkg-games-commits mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to