def read(pac_path, read_inner=False): f = open(pac_path, 'rb') assert f.read(4) == b'KCAP' util.log('\nReading PAC', pac_path, level=util.LOG_INFO) files = OrderedDict() f.seek(0x04, 1) file_count = util.readlong(f) util.log('{:d} files in archive'.format(file_count), level=util.LOG_INFO) if read_inner: import fmt_omo for i in range(0, file_count): f.seek(0x10 + i*4) f.seek(util.readlong(f)) file_name = util.readstring(f) m = re.match('(.*)([A-Z])([0-9][0-9])(.*)\.([a-z]{3})', file_name) if not m: util.log('Unmatched file skipped', file_name, level=util.LOG_ERROR) continue bodygroup = m.group(1) motion_name = m.group(4) ext = m.group(5) f.seek(0x10 + (file_count * 4) + (i * 4)) file_offset = util.readlong(f) f.seek(0x10 + (file_count * 8) + (i * 4)) file_len = util.readlong(f) f.seek(file_offset) file_contents = f.read(file_len) assert(len(file_contents) == file_len) if read_inner and m.group(5) == 'omo': util.log('\nReading OMO', file_name, level=util.LOG_INFO) files[file_name] = fmt_omo.read(file_contents) else: files[file_name] = file_contents return files
def read(pac_path, read_inner=False): f = open(pac_path, 'rb') assert f.read(4) == b'KCAP' util.log('\nReading PAC', pac_path, level=util.LOG_INFO) files = OrderedDict() f.seek(0x04, 1) file_count = util.readlong(f) util.log('{:d} files in archive'.format(file_count), level=util.LOG_INFO) if read_inner: import fmt_omo for i in range(0, file_count): f.seek(0x10 + i * 4) f.seek(util.readlong(f)) file_name = util.readstring(f) m = re.match('(.*)([A-Z])([0-9][0-9])(.*)\.([a-z]{3})', file_name) if not m: util.log('Unmatched file skipped', file_name, level=util.LOG_ERROR) continue bodygroup = m.group(1) motion_name = m.group(4) ext = m.group(5) f.seek(0x10 + (file_count * 4) + (i * 4)) file_offset = util.readlong(f) f.seek(0x10 + (file_count * 8) + (i * 4)) file_len = util.readlong(f) f.seek(file_offset) file_contents = f.read(file_len) assert (len(file_contents) == file_len) if read_inner and m.group(5) == 'omo': util.log('\nReading OMO', file_name, level=util.LOG_INFO) files[file_name] = fmt_omo.read(file_contents) else: files[file_name] = file_contents return files
if __name__ == '__main__': util.log_level = util.LOG_INFO paths = get_fighter_paths('S:\\SSB4\\extracted_content', 'yoshi') bones, bone_uids = fmt_vbn.read(paths['vbn']) archive = fmt_pac.read(paths['pac']) # convert OMOs into JSON animation format animations = [] for f, f_data in archive.items(): m = re.match('.+([A-Z])\d{2}(.+)\.([a-z]{3})', f) if m.group(3) == 'omo' and (m.group(1) == 'A'): util.log('\nReading OMO', f, level=util.LOG_INFO) motion = fmt_omo.read(f_data, debug_bones=bones, debug_bone_ids=bone_uids) animation = { 'name': m.group(2), 'fps': 30, 'length': motion['frame_count'] / 30, 'hierarchy': [{ 'parent': b['parent'], 'keys': [] } for b in bones] } if motion['unknown']: animation['name'] += '_INCOMPLETE' for channel in motion['channels']: bone_index = bone_uids[channel['bone']]
'pac': os.path.join(base, 'fighter', name, 'motion', 'body', 'main.pac') } if __name__ == '__main__': util.log_level = util.LOG_INFO paths = get_fighter_paths('S:\\SSB4\\extracted_content', 'yoshi') bones, bone_uids = fmt_vbn.read(paths['vbn']) archive = fmt_pac.read(paths['pac']) # convert OMOs into JSON animation format animations = [] for f, f_data in archive.items(): m = re.match('.+([A-Z])\d{2}(.+)\.([a-z]{3})', f) if m.group(3) == 'omo' and (m.group(1) == 'A'): util.log('\nReading OMO', f, level=util.LOG_INFO) motion = fmt_omo.read(f_data, debug_bones=bones, debug_bone_ids=bone_uids) animation = { 'name': m.group(2), 'fps': 30, 'length': motion['frame_count'] / 30, 'hierarchy': [{ 'parent': b['parent'], 'keys': []} for b in bones] } if motion['unknown']: animation['name'] += '_INCOMPLETE' for channel in motion['channels']: bone_index = bone_uids[channel['bone']] for i, frame in enumerate(channel['frames']): frame['time'] = i / 30 if 'pos' in frame: frame['pos'] = list(np.add(bones[bone_index]['pos'], frame['pos']))