diff options
| author | きゃれい <[email protected]> | 2017-08-16 03:10:31 +0000 |
|---|---|---|
| committer | きゃれい <[email protected]> | 2017-08-16 03:10:31 +0000 |
| commit | 1a824b3ed577ad99a3c4b6671e3e871079633d75 (patch) | |
| tree | 3763caf7353a98f8e93fae9dbb490dd6d293fb18 /repack.py | |
| parent | Fix jankiness when repacker chooses not to compress a non-blacklisted file (diff) | |
| download | kiwad-repacker-master.tar.xz kiwad-repacker-master.zip | |
saving as entry
Diffstat (limited to 'repack.py')
| -rw-r--r-- | repack.py | 257 |
1 files changed, 129 insertions, 128 deletions
@@ -1,128 +1,129 @@ -#!/usr/bin/env python3
-
-import argparse
-import io
-import pathlib
-import re
-import zlib
-
-# The MIT License (MIT)
-# Copyright (c) 2016 kyarei
-#
-# 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.
-
-# Usage: python3 repack.py <root dir> <archive name>
-
-# Parse the arguments
-
-parser = argparse.ArgumentParser(description='Repack Wizard101 WAD files.')
-parser.add_argument('sourcePath', type=str,
- help='the root directory of the files to be archived')
-parser.add_argument('archivePath', type=str,
- help='the path of the archive file to be made')
-parser.add_argument('blacklist', type=str, nargs='?', default='',
- help='a file containing patterns to avoid compressing')
-parser.add_argument('--verbose', '-v', type=bool,
- help='if enabled, use diagnostics')
-
-args = parser.parse_args()
-
-# Get all files in the directory specified
-
-root = pathlib.Path(args.sourcePath)
-files = root.glob("**/*");
-blacklist = set()
-if args.blacklist != '':
- blacklistPatterns = re.split('\s', open(args.blacklist).read(-1))
- for p in blacklistPatterns:
- if p != '':
- blacklist.update(set(root.glob(p)))
-entries = []
-offset = 14 # Precalculate offset of data section in loop below
-
-# Make entries of all files
-
-for f in files:
- if f.is_file():
- with f.open(mode="rb") as h:
- contents = h.read(-1)
- isCompressed = not f in blacklist
- zSize = 0xFFFFFFFF
- uSize = len(contents)
- if isCompressed:
- compressedContents = zlib.compress(contents)
- zSize = len(compressedContents)
- isCompressed = zSize < uSize
- name = str(f.relative_to(root))
- crc = zlib.crc32(contents)
- entry = {
- "contents": compressedContents if isCompressed else contents,
- "uSize": uSize,
- "zSize": zSize,
- "name": name,
- "isCompressed": isCompressed,
- "crc": crc
- }
- entries.append(entry)
- offset += 22 + len(name)
- if args.verbose:
- print("> File %s acknowledged" % name)
-
-if args.verbose:
- print("%d files acknowledged" % len(entries))
-
-# Open the output file
-
-out = open(args.archivePath, "wb");
-
-def writeByte(stream, val):
- stream.write(bytes([val]))
-def writeInt(stream, val):
- stream.write(val.to_bytes(4, byteorder="little"))
-
-if args.verbose:
- print("Opened output file; writing data...")
-
-# Write magic string
-out.write(b"KIWAD")
-# Write version
-writeInt(out, 2)
-# Write number of files
-writeInt(out, len(entries))
-# Write dummy byte
-writeByte(out, 1)
-# Write file ENTRIES
-for e in entries:
- netSize = e["zSize"] if e["isCompressed"] else e["uSize"]
- writeInt(out, offset) # Offset
- writeInt(out, e["uSize"])
- writeInt(out, e["zSize"])
- writeByte(out, e["isCompressed"])
- writeInt(out, e["crc"])
- writeInt(out, len(e["name"].encode()) + 1) # includes terminating null
- out.write(e["name"].encode())
- writeByte(out, 0)
- offset += netSize
- if args.verbose:
- print("> Wrote ENTRY for %s" % e["name"])
-# Write file DATA
-for e in entries:
- out.write(e["contents"])
- if args.verbose:
- print("> Wrote DATA for %s" % e["name"])
+#!/usr/bin/env python3 + +import argparse +import io +import pathlib +import re +import zlib + +# The MIT License (MIT) +# Copyright (c) 2016 kyarei +# +# 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. + +# Usage: python3 repack.py <root dir> <archive name> + +# Parse the arguments + +parser = argparse.ArgumentParser(description='Repack Wizard101 WAD files.') +parser.add_argument('sourcePath', type=str, + help='the root directory of the files to be archived') +parser.add_argument('archivePath', type=str, + help='the path of the archive file to be made') +parser.add_argument('blacklist', type=str, nargs='?', default='', + help='a file containing patterns to avoid compressing') +parser.add_argument('--verbose', '-v', type=bool, + help='if enabled, use diagnostics') + +args = parser.parse_args() + +# Get all files in the directory specified + +root = pathlib.Path(args.sourcePath) +files = root.glob("**/*"); +blacklist = set() +if args.blacklist != '': + blacklistPatterns = re.split('\s', open(args.blacklist).read(-1)) + for p in blacklistPatterns: + if p != '': + blacklist.update(set(root.glob(p))) +entries = [] +offset = 14 # Precalculate offset of data section in loop below + +# Make entries of all files + +for f in files: + if f.is_file(): + with f.open(mode="rb") as h: + contents = h.read(-1) + isCompressed = not f in blacklist + zSize = 0xFFFFFFFF + uSize = len(contents) + if isCompressed: + compressedContents = zlib.compress(contents) + zSize = len(compressedContents) + isCompressed = zSize < uSize + name = str(f.relative_to(root)) + name = name.replace("\\", "/") + crc = zlib.crc32(contents) + entry = { + "contents": compressedContents if isCompressed else contents, + "uSize": uSize, + "zSize": zSize, + "name": name, + "isCompressed": isCompressed, + "crc": crc + } + entries.append(entry) + offset += 22 + len(name) + if args.verbose: + print("> File %s acknowledged" % name) + +if args.verbose: + print("%d files acknowledged" % len(entries)) + +# Open the output file + +out = open(args.archivePath, "wb"); + +def writeByte(stream, val): + stream.write(bytes([val])) +def writeInt(stream, val): + stream.write(val.to_bytes(4, byteorder="little")) + +if args.verbose: + print("Opened output file; writing data...") + +# Write magic string +out.write(b"KIWAD") +# Write version +writeInt(out, 2) +# Write number of files +writeInt(out, len(entries)) +# Write dummy byte +writeByte(out, 1) +# Write file ENTRIES +for e in entries: + netSize = e["zSize"] if e["isCompressed"] else e["uSize"] + writeInt(out, offset) # Offset + writeInt(out, e["uSize"]) + writeInt(out, e["zSize"]) + writeByte(out, e["isCompressed"]) + writeInt(out, e["crc"]) + writeInt(out, len(e["name"].encode()) + 1) # includes terminating null + out.write(e["name"].encode()) + writeByte(out, 0) + offset += netSize + if args.verbose: + print("> Wrote ENTRY for %s" % e["name"]) +# Write file DATA +for e in entries: + out.write(e["contents"]) + if args.verbose: + print("> Wrote DATA for %s" % e["name"]) |