From b4b12fa9221252434feac7e36ddfecdac0c2b5ec Mon Sep 17 00:00:00 2001 From: BlueishSapphire Date: Thu, 5 Mar 2026 22:55:21 -0500 Subject: [PATCH] Create script to convert files between .arc and .zip --- arcconv.py | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 arcconv.py diff --git a/arcconv.py b/arcconv.py new file mode 100644 index 000000000..9ab7db909 --- /dev/null +++ b/arcconv.py @@ -0,0 +1,81 @@ +import sys, struct +from zipfile import ZipFile, Path +from io import BytesIO + + +def usage(exe_name: str): + print(f"usage: {exe_name} ") + print(" command: either arc2zip or zip2arc") + sys.exit(1) + + +def main(): + exe_name = sys.argv[0] + if len(sys.argv) != 4: usage(exe_name) + command = sys.argv[1] + in_filename = sys.argv[2] + out_filename = sys.argv[3] + + if command == "arc2zip": + arc_to_zip(in_filename, out_filename) + elif command == "zip2arc": + zip_to_arc(in_filename, out_filename) + else: + usage(exe_name) + + +def arc_to_zip(in_filename: str, out_filename: str): + with open(in_filename, "rb") as file: + data = file.read() + buf = BytesIO(data) + + with ZipFile(out_filename, "w") as zipfile: + entry_count = struct.unpack(">I", buf.read(4))[0] + files = [] + + for _ in range(entry_count): + strlen = struct.unpack(">H", buf.read(2))[0] + fmt = f">{strlen}s2I" + fmt_size = struct.calcsize(fmt) + (filename, offset, size) = struct.unpack(fmt, buf.read(fmt_size)) + filename = filename.decode("UTF-8").strip("\0").replace("\\", "/") + file_path = Path(zipfile, filename) + files.append((filename, data[offset:offset + size])) + +# files.sort(key=lambda pair: pair[0]) + for filename, contents in files: + zipfile.writestr(filename, contents) + + +def zip_to_arc(in_filename: str, out_filename: str): + data_buf = bytearray() + + with open(out_filename, "wb") as out_file: + files = [] + + with ZipFile(in_filename, "r") as zip_file: + files.extend((file.filename, zip_file.read(file)) for file in zip_file.filelist) + +# files.sort(key=lambda pair: pair[0]) + + header_length = ( + sum(len(file[0].encode('utf-8')) for file in files) + + len(files) * struct.calcsize(f">H2I") + + struct.calcsize("I") + ) + + out_file.write(struct.pack(">I", len(files))) + + for filename, contents in files: + offset = header_length + len(data_buf) + file_path = filename.replace("/", "\\").encode('utf-8') + out_file.write(struct.pack( + f">H{len(file_path)}s2I", len(file_path), file_path, offset, len(contents) + )) + data_buf.extend(contents) + + out_file.write(data_buf) + +if __name__ == "__main__": + main() +