r13793 - packages/trunk/funguloids/debian
Fabian Greffrath
fabian-guest at alioth.debian.org
Thu Oct 4 10:54:20 UTC 2012
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 <mcitadel at gmail.com> 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
+
More information about the Pkg-games-commits
mailing list