当前位置:首页 > 影视动漫 >

ps2电光火石3怎么存档(ps2模拟器电光火石2完美存档)

来源:原点资讯(www.yd166.com)时间:2024-01-16 07:17:12作者:YD166手机阅读>>

上一篇文章中我们解析了PS2存储卡的文件系统,这次直接实战,编写python代码导出指定的游戏存档。

01 解析SuperBlock

SuperBlock结构如下,大小为340字节:

struct SuperBlock { char magic[28]; char version[12]; uint16 page_size; uint16 pages_per_cluster; uint16 pages_per_block; uint16 unknown; // ignore uint32 clusters_per_card; uint32 alloc_offset; uint32 alloc_end; uint32 rootdir_cluster; uint32 backup_block1; // ignore uint32 backup_block2; // ignore uint32 unknown[2]; // ignore uint32 ifc_list[32]; uint32 bad_block_list[32]; // ignore byte card_type; byte card_flags; byte unknown; // ignore byte unknown; // ignore };

使用Struct.unpack()解包:

struct.Struct("<28s12sHHH2xLLLL4x4x8x128s128xbbxx").unpack(byte_val)

得到page_size和pages_per_cluster。

02 读取page和cluster

根据公式计算page和cluster大小:

self.spare_size = (self.page_size // 128) * 4 # 备用区域字节数 self.raw_page_size = self.page_size self.spare_size # 算上备用区域的page字节数 self.cluster_size = self.page_size * self.pages_per_cluster # 簇字节数

读取page和cluster,spare area里的内容是被舍弃掉的:

def read_page(self, n): # n为page编号 offset = self.raw_page_size * n return self.byte_val[offset: offset self.page_size] def read_cluster(self, n): # n为cluster编号 page_index = n * self.pages_per_cluster byte_buffer = bytearray() for i in range(self.pages_per_cluster): byte_buffer = self.read_page(page_index i) return bytes(byte_buffer)03 构建FAT矩阵

从上一篇文章知道FAT矩阵的构建方式如下:

ps2电光火石3怎么存档,ps2模拟器电光火石2完美存档(1)

添加图片注释,不超过 140 字(可选)

def __build_fat_matrix(self): indirect_fat_matrix = self.__build_matrix(self.ifc_list) # 从ifc_list构建间接FAT indirect_fat_matrix = indirect_fat_matrix.reshape(indirect_fat_matrix.size) # 间接FAT是个一维数组 indirect_fat_matrix = [x for x in indirect_fat_matrix if x != Fat.UNALLOCATED] # 排除掉0xFFFFFFFF这种未分配的 fat_matrix = self.__build_matrix(indirect_fat_matrix) # 从间接FAT构建直接FAT return fat_matrix def __build_matrix(self, cluster_list): matrix = np.zeros((len(cluster_list), self.fat_per_cluster), np.uint32) # 初始化矩阵 for index, v in enumerate(cluster_list): # 遍历cluster cluster_value = self.read_cluster(v) # 读出每个cluster的256个FAT cluster_value_unpacked = np.frombuffer(cluster_value, np.uint32) for index0, v0 in enumerate(cluster_value_unpacked): matrix[index, index0] = v0 # 给矩阵赋值 return matrix def get_fat_value(self, n): # 给出簇编号n,找到其对应的FAT的值 value = self.fat_matrix[(n // self.fat_per_cluster) % self.fat_per_cluster, n % self.fat_per_cluster] return value ^ Fat.ALLOCATED_BIT if value & Fat.ALLOCATED_BIT > 0 else value # 最高位为8代表正常使用的簇,其它值代表簇未分配,最高位为8时,取低31位的整形值04 条目数据结构

条目是所有文件和目录的元数据,条目的数据结构如下:

struct Entry { uint16 mode; uint16 unknown; // ignore uint32 length; char created[8]; uint32 cluster; uint32 dir_entry; // ignore char modified[8]; uint32 attr; // ignore char padding[28]; // ignore char name[32]; char padding[416]; // ignore };

使用struct.unpack()解包:

struct.Struct("<H2xL8sL4x8s4x28x32s416x").unpack(byte_val)

每个条目的大小为512字节,条目里最重要的字段是cluster,标识了该条目对应的文件或目录的簇编号。如果本条目是目录,则对应的簇编号是“条目簇”;如果本条目是文件,则对应的簇编号是“文件簇”。另一个重要字段是length,如果本条目是目录,则对应的是目录下的条目数;如果本条目是文件,则对应的是文件的字节数。

05 解析“条目簇”和“数据簇”

def read_entry_cluster(self, cluster_offset): # 读取条目,条目是512字节,一个簇可以包含多个条目 cluster_value = self.read_cluster(cluster_offset self.alloc_offset) return Entry.build(cluster_value) def read_data_cluster(self, entry): # 读取数据,要从第一个簇开始读取到文件结束 byte_buffer = bytearray() chain_start = entry.cluster bytes_read = 0 while chain_start != Fat.CHAIN_END: to_read = min(entry.length - bytes_read, self.cluster_size) byte_buffer = self.read_cluster(chain_start self.alloc_offset)[:to_read] bytes_read = to_read chain_start = self.get_fat_value(chain_start) return bytes(byte_buffer) def build(byte_val): entry_count = len(byte_val) // Entry.__size entries = [] for i in range(entry_count): entries.append(Entry(byte_val[i * Entry.__size: i * Entry.__size Entry.__size])) return entries06 读取存储卡中的所有文件

上一篇文章说过,根目录没有条目,它的首个“条目簇”在超级块的rootdir_cluster中,它的“包含条目数”在.这个条目中。

要读取存储卡中的所有文件,第一步是解析根目录下所有条目,再解析条目下所有文件。因此只要循环调用以下方法:

def find_sub_entries(self, parent_entry): chain_start = parent_entry.cluster sub_entries = [] while chain_start != Fat.CHAIN_END: entries = self.read_entry_cluster(chain_start) for e in entries: if len(sub_entries) < parent_entry.length: sub_entries.append(e.unpack()) chain_start = self.get_fat_value(chain_start) return [x for x in sub_entries if not x.name.startswith('.')]

结果如下:

BISCPS-15119sv01 GameData BISCPS-15119sv01 icon00.ico icon.sys BISCPS-15116sv01 GameData BISCPS-15116sv01 icon00.ico icon.sys BASLUS-21441DBZT2 icon.sys dbzsn.ico BASLUS-21441DBZT2 ...07 导出游戏存档

既然所有文件条目都已经读取出来了,我们只要写个方法,根据输入的游戏名称,即可导出目录下的所有文件。

def export(self, name, dest): dir_path = dest os.sep name if not os.path.exists(dir_path): os.mkdir(dir_path) entries = self.lookup_entry_by_name(name) for e in entries: if e.is_file(): with open(dir_path os.sep e.name, 'wb') as f: f.write(self.ps2mc.read_data_cluster(e))08 结尾

至此,我们已经可以把一个游戏的存档从存储卡中导出来了。项目完整代码可以访问:。下一篇我们将分析一下每个存档文件里的icon.sys和xxx.ico文件,这两个文件是存档3d特效的数据文件。

09 参考文献

,

栏目热文

ps2电光火石3必杀技(ps2电光火石3怎么设置中文)

ps2电光火石3必杀技(ps2电光火石3怎么设置中文)

《龙珠》是日本漫画家鸟山明先生于1984年,连载在《周刊少年jump》上的漫画作品。不知道有多少玩家和我一样,从小对这个...

2024-01-16 07:47:13查看全文 >>

ps2电光火石3镜像(ps2电光火石3怎么设置中文)

ps2电光火石3镜像(ps2电光火石3怎么设置中文)

根据往常经验,一月份的院线市场总是最冷清的。春节档厮杀前夕,门可罗雀。但。今年是个例外。因为还有这部电影镇住场子。让鱼叔...

2024-01-16 07:45:23查看全文 >>

ps2电光火石全人物(ps2电光火石怎么存档)

ps2电光火石全人物(ps2电光火石怎么存档)

IT之家 3 月 6 日消息,在今日举行的“龙珠 BATTLE HOUR 2023”活动中,万代南梦宫正式公布了《龙珠 ...

2024-01-16 07:33:40查看全文 >>

ps2七龙珠电光火石3键位手柄设置(ps2七龙珠电光火石3界面翻译)

ps2七龙珠电光火石3键位手柄设置(ps2七龙珠电光火石3界面翻译)

PS2模拟器是一款免费、并且源代码开放的软件,发布于在GNU通用公共许可证下,是一款PlayStation 2模拟器软件...

2024-01-16 07:37:26查看全文 >>

华为手表如何开启运动模式(华为手表开始运动怎么设置)

华为手表如何开启运动模式(华为手表开始运动怎么设置)

8月初的华为开发者大会2023上,华为重磅发布了HarmonyOS 4,获得了超高的关注度。作为华为智能穿戴品类旗舰,华...

2024-01-16 07:11:14查看全文 >>

ps2电光火石2解锁人物(ps2电光火石2隐藏剧情)

ps2电光火石2解锁人物(ps2电光火石2隐藏剧情)

从简陋点阵到吊打动画:龙珠游戏进化30年网易爱玩百万稿费活动投稿,作者 托比亚,未经授权请勿转载在日本尚未首发之前,《龙...

2024-01-16 07:08:11查看全文 >>

ps2电光火石3怎么融合(ps2电光火石3怎么设置第二人)

ps2电光火石3怎么融合(ps2电光火石3怎么设置第二人)

引言说起《龙珠》(Dragon Ball)想必各位并不陌生。这部风靡全球的长篇漫画,陪伴我们儿时成长的经典动画,承载着我...

2024-01-16 07:20:32查看全文 >>

电脑网易云怎么循环一首歌(网易云音乐怎么循环三首歌)

电脑网易云怎么循环一首歌(网易云音乐怎么循环三首歌)

锋哥作为网易云音乐的老用户,已经不止一次吐槽这个音乐软件了,整合直播、算法智障(老推荐一些翻唱的、串烧、DJ歌曲)、下架...

2024-01-16 07:49:15查看全文 >>

电脑网易云怎么单曲循环(电脑网易云单曲循环在哪设置)

电脑网易云怎么单曲循环(电脑网易云单曲循环在哪设置)

AMD笔记本在最近几年算是缓口气了,从最初的低压版锐龙处理器开始慢慢地收复城池,尽管和英特尔在移动平台上还有一定的距离,...

2024-01-16 07:15:31查看全文 >>

电脑登录网易云没有歌怎么弄(网易云电脑端怎么买歌)

电脑登录网易云没有歌怎么弄(网易云电脑端怎么买歌)

音乐作为日常生活中人与人之间的第二种语言沟通方式,你可以通过它来表达你现在的任何情绪,就像写一首诗一样,通过不一样的方式...

2024-01-16 07:34:02查看全文 >>

文档排行