aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbluebear94 <[email protected]>2016-07-22 15:06:11 -0400
committerbluebear94 <[email protected]>2016-07-22 15:06:11 -0400
commitb8bb1f4070eec1ffd7f6148eb3839ce893f3bfe7 (patch)
tree4a71663c9ccd05cd93114c8a23555a59c399cd04
downloadkiwad-repacker-b8bb1f4070eec1ffd7f6148eb3839ce893f3bfe7.tar.xz
kiwad-repacker-b8bb1f4070eec1ffd7f6148eb3839ce893f3bfe7.zip
Initial commit
-rwxr-xr-x.gitignore2
-rwxr-xr-xLICENSE20
-rwxr-xr-xREADME.md16
-rw-r--r--repack.py115
4 files changed, 153 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..587a903
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+test*/
+
diff --git a/LICENSE b/LICENSE
new file mode 100755
index 0000000..8049bba
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+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.
diff --git a/README.md b/README.md
new file mode 100755
index 0000000..b6c9b91
--- /dev/null
+++ b/README.md
@@ -0,0 +1,16 @@
+## cripper
+
+the C program that rips your PH3 archives apart
+
+### Usage:
+
+ # to compile it:
+ make
+ # to rip apart an archive:
+ ./cripper --verbose archive.dat path/to/destination
+ # same, but doesn't produce output:
+ ./cripper archive.dat path/to/destination
+
+### Further reading
+
+[Notes on the format](https://gist.github.com/bluebear94/f5a7afe5396b2626d63546bda400bffa)
diff --git a/repack.py b/repack.py
new file mode 100644
index 0000000..e4d7116
--- /dev/null
+++ b/repack.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python3
+
+import argparse
+import io
+import pathlib
+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('--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("**/*");
+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)
+ compressedContents = zlib.compress(contents)
+ uSize = len(contents)
+ zSize = len(compressedContents)
+ name = str(f.relative_to(root))
+ isCompressed = zSize < uSize
+ crc = zlib.crc32(contents)
+ entry = {
+ "contents": contents,
+ "compressedContents": compressedContents,
+ "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
+ print("> Wrote ENTRY for %s" % e["name"])
+# Write file DATA
+for e in entries:
+ out.write(e["compressedContents"] if e["isCompressed"] else e["contents"])
+ print("> Wrote DATA for %s" % e["name"])