s1986q 发表于 2024-4-1 08:35

解包某电钢琴学习机的歌曲包 python版移植

本帖最后由 s1986q 于 2024-4-1 12:59 编辑

原精华帖:https://www.52pojie.cn/thread-1908192-1-1.html
c# 每次使用都很费事,转换python代码,就可以。python包不大。
使用的内置函数。
代码bug修复
import os
import struct
import sys

# 定义一个函数,从文件数据中获取密钥
def get_key(file_data):
    """
    从文件数据中提取密钥

    参数:
    file_data (字节串):包含数据的文件内容

    返回:
    key (字节串):提取的密钥
    """
    key_a = file_data
    key_b = file_data
    return bytes((key_b - key_a) & 0xff for i in range(32))

# 定义一个函数,从文件数据中获取所有目录信息
def get_all_dirs(file_data):
    """
    从文件数据中提取所有目录的信息

    参数:
    file_data (字节串):包含数据的文件内容

    返回:
    dirs (列表):包含目录名称、目录数据长度和目录数据偏移的元组列表
    """
    dirs = []
    dir_num = struct.unpack('<i', file_data)
    for i in range(dir_num):
      offset = 1280 + i * 128
      item = file_data
      item = bytes((item - key) & 0xff for j in range(128))
      dir_name = item[:120].decode('gbk').rstrip('\x00')
      dir_data_length = struct.unpack('<i', item) << 7
      dir_data_offset = struct.unpack('<i', item)
      dirs.append((dir_name, dir_data_length, dir_data_offset))
    return dirs

# 定义一个函数,从文件数据中获取所有文件信息
def get_all_files(file_data, dir_data_offset, dir_data_length):
    """
    从文件数据中提取特定目录下的所有文件信息

    参数:
    file_data (字节串):包含数据的文件内容
    dir_data_offset (整数):目录数据的偏移量
    dir_data_length (整数):目录数据的长度

    返回:
    files (列表):包含文件名称、歌曲数据偏移和歌曲数据长度的元组列表
    """
    files = []
    for i in range(dir_data_length // 128):
      offset = dir_data_offset + i * 128
      item = file_data
      item = bytes((item - key) & 0xff for j in range(128))
      file_name = item[:64].decode('gbk').rstrip('\x00')
      song_data_offset = struct.unpack('<i', item)
      song_data_length = struct.unpack('<i', item)
      files.append((file_name, song_data_offset, song_data_length))
    return files

# 定义一个函数,从文件数据中获取歌曲数据
def get_song_data(file_data, song_data_offset, song_data_length):
    """
    从文件数据中提取歌曲数据

    参数:
    file_data (字节串):包含数据的文件内容
    song_data_offset (整数):歌曲数据的偏移量
    song_data_length (整数):歌曲数据的长度

    返回:
    song_data (字节串):提取的歌曲数据
    """
    return file_data

if __name__ == "__main__":
    # 检查命令行参数的数量是否正确
    if len(sys.argv)!= 3:
      print("调用说明: PianoCatSongDataExtractor.py <input> <output>")
      sys.exit(1)

    # 输入文件路径
    input_file = sys.argv
    # 输出目录路径
    output_dir = sys.argv

    # 以二进制模式打开输入文件并读取数据
    with open(input_file, 'rb') as f:
      data = f.read()

    # 获取密钥
    key = get_key(data)
    # 获取目录信息
    dirs = get_all_dirs(data)

    # 遍历目录信息,创建目录并提取文件信息
    for dir_info in dirs:
      os.makedirs(os.path.join(output_dir, dir_info), exist_ok=True)
      files = get_all_files(data, dir_info, dir_info)

      for file_info in files:
            print(f"{dir_info} -> {file_info}")
            # 提取歌曲数据并写入文件
            song_data = get_song_data(data, file_info, file_info)

            with open(os.path.join(output_dir, dir_info, file_info + ".mid"), 'wb') as f:
                f.write(song_data)

anning666 发表于 2024-4-1 08:57

python相比多数语言,真的简洁了很多
大爱python~

andyTT 发表于 2024-4-1 09:19

感谢大佬的分享~ python就很友好

T2ao 发表于 2024-4-1 11:12

python真的方便,大佬共享代码更方便,感谢大佬

light323 发表于 2024-4-1 11:22

牛逼楼主

seawaycao 发表于 2024-4-1 12:23


感谢大佬的分享~ python就很友好

blindcat 发表于 2024-4-1 16:07

厉害了我的哥

16603175200 发表于 2024-4-2 09:53

怎么使用啊

16603175200 发表于 2024-4-2 09:54

有解出来的包吗? 分享下吧 亲人

16603175200 发表于 2024-4-2 10:16

ok了   cmd就行
页: [1] 2
查看完整版本: 解包某电钢琴学习机的歌曲包 python版移植