sol文件解析AS2.0——小游戏上古神器2存档通过Python解析

楔子

突然想起来小时玩的上古神器这个游戏,于是下载下来玩玩。用的ruffle来打开swf文件。

遇到bug卡关过不去,想着修改存档,网上找了一圈,没找到有用的东西。

只好自己写了个解析游戏存档json的python代码,方便自己改存档,哈哈哈

sol文件解析 AS2.0

头部信息

2个字节(文件标识):00 BF

4个字节(文件字节数 - 6):00 00 08 24

10个字节(固定的):54 43 53 4F 00 04 00 00 00 00

2个字节(SharedObject表名的长度):00 08

N个字节(表名:savegame):73 61 76 65 67 61 6D 65

4个字节(AS版本号 2.0版本):00 00 00 00

1个字节(分隔符):00

数据区

type: 00

如:03 63 6A 31 00 40 20 00 00 00 00 00 00 00 00

1个字节(key长度):03

N个字节(key:cj1):63 6A 31

1个字节(value类型,8字节数字):00

N个字节(value,根据类型判断字节数):40 20 00 00 00 00 00 00

2个字节(结束符):00 00

type: 06

如:09 73 68 6F 75 77 65 69 32 31 06 00 00

1个字节(key长度):09

N个字节(key:shouwei21):73 68 6F 75 77 65 69 32 31

1个字节(value类型,null):06

2个字节(结束符):00 00

type: 01

如:09 6A 69 6E 67 73 68 75 69 31 01 01 00 00

1个字节(key长度):09

N个字节(key:jingshui1):6A 69 6E 67 73 68 75 69 31

1个字节(value类型,布尔类型,1个字节):01

N个字节(value,根据类型判断字节数):01

2个字节(结束符):00 00

Python解析代码

将解析的文件保存为json

import json

paramsMapList = []


def decode_sol():
    with open("./savegame.sol", "rb") as f:
        data = f.read()

        fileNameLen = int(data[16:18].hex(), 16)

        startAt = 2 + 4 + 10 + 2 + fileNameLen + 4 + 1

        print(len(data), startAt)
        i = startAt
        while i < len(data):
            param = {}
            keyLen = int(data[i:i+1].hex(), 16)
            keyName = data[i+1:i+1+keyLen].decode("utf-8")
            valueType = str(data[i+1+keyLen:i+2+keyLen].hex())
            if valueType == "00":
                value = str(data[i+2+keyLen:i+2+keyLen+8].hex())
                i = i + 2 + keyLen + 8 + 2
            elif valueType == "06":
                value = "null"
                i = i + 2 + keyLen + 2
            elif valueType == "01":
                value = str(data[i+2+keyLen:i+2+keyLen+1].hex())
                i = i + 2 + keyLen + 1 + 2
            else:
                raise BaseException(f"value type unknow: {valueType}\nlocation: {i+1+keyLen}")

            param["keyLen"] = keyLen
            param["keyName"] = keyName
            param["valueType"] = valueType
            param["value"] = value

            paramsMapList.append(param)


try:
    decode_sol()
except BaseException as e:
    print(e)
finally:
    print(json.dumps(paramsMapList))

Python根据Json生成sol

import json

sol_name = "savegame"  # 表名
sol_json_path = "./savegame.json"
sol_save_path = "./savegame_save.sol"


def save_sol(sol: list):
    sol_bytes = bytearray()

    param_len = 2 + 4 + 10 + 2 + len(sol_name) + 4 + 1
    for each in sol:
        param_len += 1 + 1 + 2
        param_len += each['keyLen']
        if each['valueType'] == "00":
            param_len += 8
        elif each['valueType'] == "01":
            param_len += 1
        else:
            pass
    param_len -= 1  # 最后的分隔符只有1个00
    file_bytes_len = (param_len - 6).to_bytes(4, "big")

    # 头部信息
    sol_bytes.extend(b"\x00\xBF")  # 文件标识
    sol_bytes.extend(file_bytes_len)  # 文件字节数 - 6
    sol_bytes.extend(b"\x54\x43\x53\x4F\x00\x04\x00\x00\x00\x00")  # 固定10字节
    sol_bytes.extend(len(sol_name).to_bytes(2, "big"))  # 表名长度
    sol_bytes.extend(sol_name.encode("utf-8"))  # 表名
    sol_bytes.extend(b"\x00\x00\x00\x00")  # AS 2.0版本
    sol_bytes.extend(b"\x00")  # 分隔符

    # 数据区
    for index, each in enumerate(sol):
        key_len: int = each["keyLen"]
        key_name: str = each["keyName"]
        value_type: str = each["valueType"]
        value: str = each["value"]

        each_bytes = bytearray()

        each_bytes.extend(key_len.to_bytes(1, "big"))  # key长度
        each_bytes.extend(key_name.encode("utf-8"))  # key
        if value_type == "00":
            each_bytes.extend(b"\x00")  # 00类型
            each_bytes.extend(int(value, 16).to_bytes(8, "big"))  # value
        elif value_type == "01":
            each_bytes.extend(b"\x01")  # 01类型
            each_bytes.extend(int(value, 16).to_bytes(1, "big"))  # value
        elif value_type == "06":
            each_bytes.extend(b"\x06")  # 06类型
        else:
            raise BaseException(f"unknown value type: {value_type}")

        if index < len(sol)-1:
            each_bytes.extend(b"\x00\x00")
        else:
            each_bytes.extend(b"\x00")

        sol_bytes.extend(each_bytes)

    with open(sol_save_path, "wb") as sol_f:
        sol_f.write(sol_bytes)


with open(sol_json_path, "r") as f:
    sol_json = json.load(f)
    save_sol(sol_json)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值