攻克《卡利斯托协议》存档提取难题:XGP-save-extractor实现方案深度解析
你还在为Xbox Game Pass版《卡利斯托协议》(The Callisto Protocol)的存档迁移发愁吗?当你想更换设备或备份进度时,却发现XGP加密存档格式无法直接访问?本文将从技术实现角度,全面解析XGP-save-extractor项目如何通过"1容器1文件"处理模式,完美解决这一难题。读完本文你将掌握:存档提取的核心原理、handler机制的工作流程、游戏配置参数的设计要点,以及从零开始为新游戏添加支持的完整步骤。
存档提取痛点与解决方案概述
XGP(Xbox Game Pass)平台采用特殊的容器化存档格式,将游戏进度文件加密存储在系统受保护目录中。这种机制虽然保障了安全性,却给玩家带来了极大不便:无法手动备份存档、跨设备迁移困难、第三方工具兼容性差。特别是对于《卡利斯托协议》这类包含多个结局的生存恐怖游戏,存档数据的安全性直接影响游戏体验完整性。
XGP-save-extractor项目通过解析Windows应用商店(Microsoft Store)的WGS(Windows Game Save)容器格式,实现了对加密存档的无损提取。其核心价值在于:
- 跨平台兼容性:将XGP专有格式转换为通用存档格式
- 数据安全保障:提供加密容器的安全解密方案
- 灵活扩展架构:通过handler机制支持多游戏适配
项目架构与核心组件
系统架构概览
关键文件功能解析
项目核心由两个文件构成,形成"配置-逻辑"分离的架构设计:
-
games.json:游戏配置数据库
- 存储游戏识别信息(名称、package标识)
- 定义存档处理规则(handler类型及参数)
- 采用JSON格式便于扩展和维护
-
main.py:核心逻辑实现
- 游戏发现与识别
- WGS容器解析引擎
- handler处理机制
- ZIP存档生成
《卡利斯托协议》支持实现详解
配置参数设计
在games.json中,《卡利斯托协议》的配置采用"1容器1文件"(1c1f)处理模式,关键参数如下:
{
"name": "The Callisto Protocol",
"package": "PUBGCorp.TheCallistoProtocolXB1_gsxfe54jwf950",
"handler": "1c1f",
"handler_args": {
"suffix": ".sav"
}
}
参数解析:
package:唯一标识,对应Windows应用商店的包名handler: "1c1f":指定"1容器1文件"处理策略handler_args.suffix:指定输出文件的扩展名
1c1f handler工作流程
"1容器1文件"处理模式是项目中应用最广泛的存档提取策略,其核心逻辑位于get_save_paths()函数中:
elif handler_name == "1c1f":
# "1 container, 1 file" (1c1f). Each container contains only one file
# which name will be the name of the container.
file_suffix = handler_args.get("suffix")
for container in containers:
fname = container["name"]
if file_suffix is not None:
# Add a suffix to the file name if configured
fname += file_suffix
fpath = container["files"][0]["path"]
save_meta.append((fname, fpath))
处理流程:
- 遍历所有发现的容器(containers)
- 以容器名称作为基础文件名
- 应用配置的文件后缀(如.sav)
- 提取容器中唯一的文件路径
- 生成存档元数据(文件名-路径映射)
容器解析核心技术
WGS容器解析是实现存档提取的关键环节,主要通过read_user_containers()函数完成:
def read_user_containers(user_wgs_dir: Path) -> Tuple[str, List[Dict[str, Any]]]:
containers_dir = user_wgs_dir
containers_idx_path = containers_dir / "containers.index"
with containers_idx_path.open("rb") as f:
# 读取容器数量
container_count = struct.unpack("<i", f.read(4))[0]
# 读取容器元数据
pkg_display_name = read_utf16_str(f)
store_pkg_name = read_utf16_str(f).split("!")[0]
creation_date = read_filetime(f)
# 解析每个容器信息
for _ in range(container_count):
container_name = read_utf16_str(f)
container_num = struct.unpack("B", f.read(1))[0]
container_guid = uuid.UUID(bytes_le=f.read(16))
# 读取容器内文件信息
container_path = containers_dir / container_guid.hex.upper()
container_file_path = container_path / f"container.{container_num}"
# 解析文件GUID与路径
with container_file_path.open("rb") as cf:
file_count = struct.unpack("<i", cf.read(4))[0]
for _ in range(file_count):
file_name = read_utf16_str(cf, 64)
file_guid = uuid.UUID(bytes_le=cf.read(16))
file_path = container_path / file_guid.hex.upper()
files.append({
"name": file_name,
"path": file_path
})
这段代码实现了三个关键功能:
- 二进制格式解析:通过
struct.unpack处理固定长度数据 - UTF-16字符串解码:读取文件名等文本信息
- GUID路径映射:将容器内文件GUID转换为实际系统路径
存档提取完整流程演示
命令执行与输出
# 克隆项目仓库
git clone https://gitcode.com/gh_mirrors/xg/XGP-save-extractor
cd XGP-save-extractor
# 运行提取工具
python main.py
# 预期输出
Xbox Game Pass for PC savefile extractor
========================================
Installed supported games:
- The Callisto Protocol
Save files for user GamerTag123:
- The Callisto Protocol.sav
Save files written to "the_callisto_protocol_GamerTag123_2025-09-11_15_30_45.zip"
提取过程状态机
扩展开发指南:为新游戏添加支持
新增游戏支持的四步流程
-
确定package名称
- 在
%LOCALAPPDATA%\Packages目录中查找游戏文件夹 - 典型格式:
Publisher.GameName_随机字符
- 在
-
分析存档容器结构
- 使用项目提供的调试工具检查容器格式
- 确定handler类型(1c1f/1cnf/特殊处理)
-
编写配置参数
{ "name": "新游戏名称", "package": "游戏package标识", "handler": "处理类型", "handler_args": { // 特定处理参数 } } -
测试与验证
- 运行提取工具确认存档生成
- 验证存档文件的完整性和可用性
常见handler类型对比
| Handler类型 | 适用场景 | 配置复杂度 | 代表游戏 |
|---|---|---|---|
| 1c1f | 简单存档,一容器一文件 | ★☆☆☆☆ | 《卡利斯托协议》《原子之心》 |
| 1cnf | 多文件存档,一容器多文件 | ★★☆☆☆ | 《哈迪斯》《赛博朋克2077》 |
| 1cnf-folder | 文件夹结构存档 | ★★★☆☆ | 《忍者龙剑传Σ》 |
| 特殊handler | 自定义格式存档 | ★★★★★ | 《控制》《星空》 |
技术难点与解决方案
容器同步状态检测
WGS容器在云同步过程中可能处于不一致状态,项目通过双重机制保障数据完整性:
def print_sync_warning(title: str):
print()
print(f" !! {title} !!")
print(" Xbox cloud save syncing might not be complete, try again later.")
print(" Extracted saves for this game might be corrupted!")
print(" Press enter to skip and continue.")
input()
当检测到容器文件缺失或GUID不匹配时,系统会提示用户可能存在的云同步问题,避免提取不完整的存档文件。
跨版本兼容性处理
针对不同游戏版本的存档格式差异,如《星空》的格式迭代,项目采用条件分支处理:
elif handler_name == "starfield":
# 检测新旧格式差异
is_new_format = "toc" in [f["name"] for f in container["files"]]
for file in container["files"]:
if is_new_format:
idx = int(file["name"].removeprefix("BlobData"))
else:
if file["name"] == "BETHESDAPFH":
idx = 0
else:
idx = int(file["name"].strip("P")) + 1
这种自适应设计确保了工具对游戏更新的兼容性。
项目优化与未来展望
潜在改进方向
- 图形界面开发:基于Tkinter或PyQt构建可视化操作界面
- 批量处理功能:支持多游戏存档的同时提取
- 存档管理系统:添加存档版本控制和自动备份
- 云存储集成:直接对接OneDrive/Google Drive等云服务
已知限制与解决方案
| 限制 | 影响 | 解决方案 |
|---|---|---|
| 依赖Python环境 | 普通用户使用门槛 | 打包为EXE可执行文件 |
| 不支持实时监控 | 需要手动运行提取 | 添加文件系统监控功能 |
| 部分游戏加密 | 提取失败 | 逆向工程扩展handler |
总结与实用技巧
XGP-save-extractor通过灵活的handler机制和清晰的配置结构,为《卡利斯托协议》等XGP游戏提供了可靠的存档提取方案。核心价值在于:
- 开放源代码:完全透明的实现,确保数据安全
- 模块化设计:易于扩展支持新游戏
- 跨平台兼容:支持所有Windows 10/11系统
实用建议:
- 定期提取存档,特别是在游戏重大更新前
- 为不同游戏的存档文件建立明确的命名规范
- 验证提取的存档文件后再进行迁移或删除操作
通过本文介绍的技术细节,不仅可以掌握《卡利斯托协议》的存档提取方法,更能理解整个XGP存档系统的工作原理,为自主扩展新游戏支持奠定基础。项目持续更新中,欢迎贡献代码或反馈问题,共同完善这一实用工具。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



