from io import BytesIO
from pathlib import Path
from zipfile import ZipFile
from io import BufferedReader
def parse(r: BufferedReader, r2: BufferedReader, outPath: Path):
count = int.from_bytes(r.read(4), 'little')
for _ in range(count):
nameLen = r.read(1)[0]
name = bytes(i ^ nameLen for i in r.read(nameLen))
start = int.from_bytes(r.read(4), 'little') - name[-6] - nameLen
size = int.from_bytes(r.read(4), 'little') - name[-7] - nameLen
new = outPath.joinpath(name.decode())
new.parent.mkdir(parents=True, exist_ok=True)
r2.seek(start)
if new.is_file():
print(f'存在重名文件 --- {new.as_posix()}')
with open(new, 'wb') as w: w.write(r2.read(size))
def batch(datPath: str = '', outPath: str = '', subfolder: bool = False):
path = Path(datPath) if datPath else Path.cwd()
move = (Path(outPath) if outPath else path).joinpath('Extract')
need = [i for i in (path.rglob('*.dmxpkg') if subfolder else path.glob('*.dmxpkg'))]
for i in need:
with ZipFile(i) as z:
names = {j.lower():j for j in z.namelist() if j.lower().endswith(('.dat', '.dic'))}
files: dict[str, str] = {}
for i in names:
if i.endswith('.dat'): continue
v = f'{i[:-3]}dat'
if v not in names:
print(f'缺少dat文件 --- {i}')
continue
files[i] = v
if not files:
print(f'没有dat和dic文件 --- {i}')
for k, v in files.items():
with z.open(names[k]) as z1, z.open(names[v]) as z2:
f = BytesIO(z1.read())
f2 = BytesIO(z2.read())
parse(f, f2, move)
if __name__ == '__main__':
path = r'' # 游戏文件所在的路径
outPath = r'' # 导出文件的路径
subfolder = False # 是否查找字文件夹内的.dmxpkg文件
batch(path, outPath, subfolder)
批量解压dmxpkg