diff --git a/pack/packer.py b/pack/packer.py index bc1f7d7..ce14762 100644 --- a/pack/packer.py +++ b/pack/packer.py @@ -178,8 +178,10 @@ def create_archives(self): real_path = os.path.join(archive["dir"], base_path) out_path = os.path.join(temp_dir, archive["name"], base_path) - self.progress.setValue(self.progress.value() + 1) - self.progress.setLabelText("Reading...\n%s" % real_path) + self.file_count += 1 + if self.file_count % 25 == 0: + self.progress.setLabelText("Reading...\n" + full_path) + self.progress.setValue(self.file_count) # All items in the CPK list should be files. # Therefore, if we have a directory, then it needs to be packed. @@ -226,13 +228,91 @@ def create_archives(self): eboot.overwrite(BitStream(uintle = file_size, length = 32), toc_info[entry][1] * 8) del table_of_contents + + def pack_dir(self, dir, handler, file_list = None, align_toc = 16, align_files = 16, eof = False): + + table_of_contents = {} + + if file_list == None: + file_list = sorted(os.listdir(dir)) + + num_files = len(file_list) + + toc_length = (num_files + 1) * 4 + + if eof: + toc_length += 1 + if toc_length % align_toc > 0: + toc_length += align_toc - (toc_length % align_toc) + + handler.seek(0) + handler.write(struct.pack(" + elif basename[:8] == "anagram_" and ext == ".dat" and not basename == "anagram_81": + anagram = AnagramFile(full_path) + data = anagram.pack(for_game = True).bytes + + else: + with open(full_path, "rb") as f: + data = f.read() + + else: + + temp_align_toc = 16 + temp_align_files = 4 + + if item in SPECIAL_ALIGN: + temp_align_toc = SPECIAL_ALIGN[item][0] + temp_align_files = SPECIAL_ALIGN[item][1] + elif os.path.basename(dir) in SPECIAL_ALIGN and len(SPECIAL_ALIGN[os.path.basename(dir)]) == 4: + temp_align_toc = SPECIAL_ALIGN[os.path.basename(dir)][2] + temp_align_files = SPECIAL_ALIGN[os.path.basename(dir)][3] + + if os.path.splitext(full_path)[1].lower() == ".lin": + data = self.pack_lin(full_path) + + else: + data = io.BytesIO() + with io.BufferedWriter(data) as fh: + self.pack_dir(full_path, fh, align_toc = temp_align_toc, align_files = temp_align_files, eof = eof) + fh.flush() + data = data.getvalue() + + data = bytearray(data) + file_size = len(data) + padding = 0 + + if file_size % align_files > 0: + padding = align_files - (file_size % align_files) + data.extend(bytearray(padding)) + + handler.seek(0, io.SEEK_END) + file_pos = handler.tell() + handler.write(data) + handler.seek((file_num + 1) * 4) + handler.write(struct.pack("", text) + + # Nonstop Debate lines need an extra newline at the end + # so they show up in the backlog properly. + if is_nonstop and not text[-1] == "\n": + text += "\n" + + return SCRIPT_BOM.bytes + bytearray(text, encoding = "UTF-16LE") + SCRIPT_NULL.bytes + + def pack_lin(self, dir): + + # Collect our files. + file_list = sorted(list_all_files(dir)) + + txt = [filename for filename in file_list if os.path.splitext(filename)[1].lower() == ".txt"] + wrd = [filename for filename in file_list if os.path.splitext(filename)[1].lower() == ".wrd"] + py = [filename for filename in file_list if os.path.splitext(filename)[1].lower() == ".py"] + + # If there are more than one for whatever reason, just take the first. + # We only have use for a single wrd or python file. + wrd = wrd[0] if wrd else None + py = py[0] if py else None + + # Prepare our temporary output directory. + temp_dir = tempfile.mkdtemp(prefix = "sdse-") + + # Where we're outputting our wrd file, regardless of whether it's a python + # file or a raw binary data file. + wrd_dst = os.path.join(temp_dir, "0.scp.wrd") + + if py: + # _LOGGER.info("Compiling %s to binary." % py) + try: + wrd_file = WrdFile(py) + except: + _LOGGER.warning("%s failed to compile. Parsing wrd file instead. Exception info:\n%s" % (py, traceback.format_exc())) + shutil.copy(wrd, wrd_dst) + else: + # If we succeeded in loading the python file, compile it to binary. + # wrd_file.save_bin(wrd) + wrd_file.save_bin(wrd_dst) + + else: + shutil.copy(wrd, wrd_dst) + + # Pack the text files in-place to save us a bunch of copying + # and then move it to the tmp directory with the wrd file. + if txt: + with io.FileIO(os.path.join(temp_dir, "1.dat"), "w") as h: + self.pack_dir(dir, h, file_list = txt) + + # Then pack it like normal. + data = io.BytesIO() + with io.BufferedWriter(data) as h: + self.pack_dir(temp_dir, h) + h.flush() + data = data.getvalue() + + shutil.rmtree(temp_dir) + + return data if __name__ == "__main__": pass