diff --git a/deca/builder.py b/deca/builder.py index 40b00db..f88f355 100644 --- a/deca/builder.py +++ b/deca/builder.py @@ -32,17 +32,22 @@ def build_node(self, dst_path: str, vnode: VfsNode, vfs: VfsBase, src_map): entry_old: EntrySarc = sarc_old.entries[i] entry_new: EntrySarc = sarc_new.entries[i] vpath = entry_old.vpath + if entry_old.vpath in src_map: src_files[i] = src_map[vpath] sz = os.stat(src_files[i]).st_size else: sz = entry_old.length - entry_new.offset = data_write_pos - entry_new.length = sz - data_write_pos = data_write_pos + sz - align = 4 - data_write_pos = (data_write_pos + align - 1) // align * align + if entry_old.offset == 0: + entry_new.offset = 0 + entry_new.length = sz + else: + entry_new.offset = data_write_pos + entry_new.length = sz + data_write_pos = data_write_pos + sz + align = 4 + data_write_pos = (data_write_pos + align - 1) // align * align # extract existing file fn_dst = os.path.join(dst_path, vnode.vpath.decode('utf-8')) @@ -60,21 +65,26 @@ def build_node(self, dst_path: str, vnode: VfsNode, vfs: VfsBase, src_map): for i in range(len(sarc_old.entries)): entry_old: EntrySarc = sarc_old.entries[i] entry_new: EntrySarc = sarc_new.entries[i] - if src_files[i] is None: - print(' COPYING {} from old file to new file'.format(entry_old.vpath)) - fsi.seek(entry_old.offset) - buf = fsi.read(entry_old.length) - else: - print(' INSERTING {} src file to new file'.format(entry_old.vpath)) - with open(src_files[i], 'rb') as f: - buf = f.read(entry_new.length) fso.seek(entry_new.META_entry_offset_ptr) fso.write_u32(entry_new.offset) fso.seek(entry_new.META_entry_size_ptr) fso.write_u32(entry_new.length) - fso.seek(entry_new.offset) - fso.write(buf) + + if entry_new.offset != 0: + if src_files[i] is None: + print(' COPYING {} from old file to new file'.format(entry_old.vpath)) + fsi.seek(entry_old.offset) + buf = fsi.read(entry_old.length) + else: + print(' INSERTING {} src file to new file'.format(entry_old.vpath)) + with open(src_files[i], 'rb') as f: + buf = f.read(entry_new.length) + + fso.seek(entry_new.offset) + fso.write(buf) + else: + print(' SYMLINK {}'.format(entry_old.vpath)) return fn_dst else: diff --git a/deca/ff_sarc.py b/deca/ff_sarc.py index 91e04d1..387cdeb 100644 --- a/deca/ff_sarc.py +++ b/deca/ff_sarc.py @@ -60,6 +60,8 @@ def __init__(self): self.strings0 = None self.strings = None self.entries = None + self.entries_begin = None + self.entries_end = None def deserialize(self, fin): with ArchiveFile(fin) as f: @@ -71,8 +73,10 @@ def deserialize(self, fin): assert(self.ver2 in {2, 3}) self.dir_block_len = f.read_u32() + self.entries = [] + if self.ver2 == 2: - self.entries = [] + self.entries_begin = f.tell() end_pos = f.tell() + self.dir_block_len idx = 0 while f.tell() + 12 <= end_pos: # 12 is minimum length of v2 sarc entry and they pad with some zeros @@ -88,10 +92,13 @@ def deserialize(self, fin): if len(self.strings[-1]) == 0: self.strings = self.strings[:-1] + self.entries_begin = f.tell() self.entries = [EntrySarc(index=i, vpath=self.strings[i], ) for i in range(len(self.strings))] for ent in self.entries: ent.deserialize_v3(f) + self.entries_end = f.tell() + def dump_str(self): sbuf = '' for ent in self.entries: