站里有个银与绯的帖子你可以去看看,解包方法基本没变化。只是新版解包出来的.skel文件需要处理一下文件头,代码是这个:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import os
import sys
from pathlib import Path
VERSION_MARK = bytes.fromhex("07 34 2E 31 2E 32 34") # 07 + "4.1.24"
HASH_LEN = 8
def find_all(data: bytes, needle: bytes):
pos = []
start = 0
while True:
i = data.find(needle, start)
if i == -1:
break
pos.append(i)
start = i + 1
return pos
def strip_one_skel_dat(src_path: Path, overwrite: bool, occurrence: int) -> tuple[bool, str]:
"""
Returns (success, message). On success, writes <stem>.skel next to src.
Example: Jacinta.skel.dat -> Jacinta.skel
"""
try:
data = src_path.read_bytes()
except Exception as e:
return False, f"READ_FAIL: {e}"
positions = find_all(data, VERSION_MARK)
if not positions:
return False, "MARK_NOT_FOUND"
if occurrence < 1 or occurrence > len(positions):
return False, f"BAD_OCCURRENCE: requested={occurrence} found={len(positions)} offsets={positions}"
ver_idx = positions[occurrence - 1]
spine_offset = ver_idx - HASH_LEN
if spine_offset < 0:
return False, f"BAD_OFFSET: marker_at={ver_idx} < {HASH_LEN}"
# sanity check: after 8-byte hash should be the version marker
trimmed = data[spine_offset:]
if trimmed[HASH_LEN:HASH_LEN + len(VERSION_MARK)] != VERSION_MARK:
return False, "SANITY_FAIL"
# Output: remove only the trailing ".dat"
# foo.skel.dat -> foo.skel
out_path = src_path.with_suffix("") # drops .dat
if out_path.exists() and not overwrite:
return False, f"SKIP_EXISTS: {out_path.name}"
try:
out_path.write_bytes(trimmed)
except Exception as e:
return False, f"WRITE_FAIL: {e}"
return True, f"OK offset={spine_offset} (0x{spine_offset:X}) -> {out_path.name}"
def rename_atlas_prefab(p: Path, overwrite: bool) -> tuple[bool, str]:
"""
foo.atlas.prefab -> foo.atlas
"""
if not p.name.endswith(".atlas.prefab"):
return False, "NOT_MATCH"
dst = p.with_suffix("") # drops ".prefab" -> foo.atlas
if dst.exists() and not overwrite:
return False, f"SKIP_EXISTS: {dst.name}"
try:
# If overwriting, remove dst first to avoid Windows rename errors
if dst.exists() and overwrite:
dst.unlink()
p.rename(dst)
except Exception as e:
return False, f"RENAME_FAIL: {e}"
return True, f"OK -> {dst.name}"
def iter_files(root: Path, recursive: bool):
if recursive:
yield from root.rglob("*")
else:
yield from root.glob("*")
def main():
ap = argparse.ArgumentParser(
description="Batch-strip prefix from *.skel.dat by locating 4.1.24 version marker and backing up 8 bytes; rename *.atlas.prefab -> *.atlas."
)
ap.add_argument(
"--recursive", action="store_true",
help="Also process subfolders (default: only current directory)."
)
ap.add_argument(
"--overwrite", action="store_true",
help="Overwrite existing output files if they already exist."
)
ap.add_argument(
"-n", "--occurrence", type=int, default=1,
help="If marker appears multiple times, use the Nth occurrence (1-based). Default=1"
)
ap.add_argument(
"--skip-rename", action="store_true",
help="Skip renaming *.atlas.prefab -> *.atlas."
)
ap.add_argument(
"--skip-skel", action="store_true",
help="Skip processing *.skel.dat."
)
args = ap.parse_args()
root = Path.cwd()
skel_total = skel_ok = 0
atlas_total = atlas_ok = 0
# 1) Process *.skel.dat
if not args.skip_skel:
for p in iter_files(root, args.recursive):
if p.is_file() and p.name.endswith(".skel.dat"):
skel_total += 1
ok, msg = strip_one_skel_dat(p, args.overwrite, args.occurrence)
if ok:
skel_ok += 1
print(f"[SKEL] {p.name}: {msg}")
else:
print(f"[SKEL] {p.name}: {msg}")
# 2) Rename *.atlas.prefab
if not args.skip_rename:
for p in iter_files(root, args.recursive):
if p.is_file() and p.name.endswith(".atlas.prefab"):
atlas_total += 1
ok, msg = rename_atlas_prefab(p, args.overwrite)
if ok:
atlas_ok += 1
print(f"[ATLAS] {p.name}: {msg}")
else:
print(f"[ATLAS] {p.name}: {msg}")
print("\n=== Summary ===")
if not args.skip_skel:
print(f"SKEL: {skel_ok}/{skel_total} converted")
if not args.skip_rename:
print(f"ATLAS: {atlas_ok}/{atlas_total} renamed")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\nInterrupted.", file=sys.stderr)
sys.exit(130)
简单来讲就是新版银与绯给skel文件的头部加了几个字节的数据导致直接读取会出错,需要先截掉





