首先这件事已经有国外大神分享过了破解资源包的python源码,附上链接:https://github.com/kennytm/CoCCalc/tree/master。
但是在13年10月份,SC对旗下的游戏资源包做了改版,一方面加入了新技术,一方面估计是看到了Github上的源码,进行了反破解,所以在此之后的包都无法再破解了,而我做的事就是在国外大神的研究基础上,再去破解新的包。
言归正传,首先下载游戏的安装包(废话),解压,找sc文件夹,ipa文件应该在res目录下,apk应该在assets里,找到后里面会有一堆.sc文件,所有的资源都藏在这里。先插一句,这个东西包括两层,sc为第一层,破解后的文件按照国外大神的命名,就叫.scf吧,这个文件对SC游戏的引擎而言,已经可以用了,但是对我们这些资源破解者而言,还得想办法把scf破解掉,拿到图片,这个作为第二层。
第一层.sc看着玄乎,其实本质上是一个lzma压缩包。一个正常的lzma压缩包前5字节是properties,后8字节是length,再往后是压缩内容。而事实上每个sc文件的length远不能达到8字节那么长,所以SC把第10到13字节的4个0字节删掉了(little-endian),用代码将这4个0字节加上,然后再解压就行,这部分和链接里的代码一致。
重点是第二层.scf,这块内容实在是复杂,所以很佩服国外那个大神,面对一堆数据能从其中摘出每一块每一块的内容,然后找出图片的数据块并且生成出图片。我所做的都是从他的代码里看scf的数据分块,然后对比和老版本文件的区别,一步步解开新的加密的,相比之下实在是微不足道。在这里我会把我自己发现的东西分享一下,懒得把整块代码贴上来了,用到哪贴到哪,和链接里的代码对比一下就会明白。
- attributes = [
- None,
- 'texture',
- 'shape',
- 'movie_clip',
- None,
- None,
- None,
- 'text_field',
- 'matrix',
- 'color_transform',
- 'movie_clip',
- None,
- 'movie_clip',
- 'timeline_offset',
- 'movie_clip',
- 'movie_clip',
- 'movie_clip',
- 'movie_clip',
- 'shape',
- ]
- attribute = attributes[tag_type]
- result = getattr(self, 'parse_' + attribute)(data, tag_type)
- getattr(self, attributes[tag_type] + 's').append(result)
parse_shape方法改动了两处,一处在:
- if _ == 0:
- (command_type, nothing1, length) = struct.unpack('<BhI', f.read(7))
- else:
- (nothing1, length) = struct.unpack('<BI', f.read(5))
两处nothing1就是干扰变量,这个值经过大量测试,都是1,所以不存在包含信息的可能,直接弃掉,另一处是解析data的地方:
- if length == 50:
- (tex_id, nothing2, *rest) = struct.unpack('<BB8I8h', shape_data)
- commands.append(ShapeDrawBitmapCommand(
- texture=self.textures[tex_id],
- xys=((rest[0]/-20, rest[1]/-20),
- (rest[2]/-20, rest[3]/-20),
- (rest[4]/-20, rest[5]/-20),
- (rest[6]/-20, rest[7]/-20)),
- uvs=((rest[8], rest[9]),
- (rest[10], rest[11]),
- (rest[12], rest[13]),
- (rest[14], rest[15]))
- ))
- elif length == 62:
- (tex_id, nothing2, *rest) = struct.unpack('<BB10I10h', shape_data)
- commands.append(ShapeDrawBitmapCommand(
- texture=self.textures[tex_id],
- xys=((rest[0]/-20, rest[1]/-20),
- (rest[2]/-20, rest[3]/-20),
- (rest[4]/-20, rest[5]/-20),
- (rest[6]/-20, rest[7]/-20),
- (rest[8]/-20, rest[9]/-20)),
- uvs=((rest[10], rest[11]),
- (rest[12], rest[13]),
- (rest[14], rest[15]),
- (rest[16], rest[17]),
- (rest[18], rest[19]))
- ))
- elif length == 74:
- (tex_id, nothing2, *rest) = struct.unpack('<BB12I12h', shape_data)
- commands.append(ShapeDrawBitmapCommand(
- texture=self.textures[tex_id],
- xys=((rest[0]/-20, rest[1]/-20),
- (rest[2]/-20, rest[3]/-20),
- (rest[4]/-20, rest[5]/-20),
- (rest[6]/-20, rest[7]/-20),
- (rest[8]/-20, rest[9]/-20),
- (rest[10]/-20, rest[11]/-20)),
- uvs=((rest[12], rest[13]),
- (rest[14], rest[15]),
- (rest[16], rest[17]),
- (rest[18], rest[19]),
- (rest[20], rest[21]),
- (rest[22], rest[23]))
- ))
- elif length == 86:
- (tex_id, nothing2, *rest) = struct.unpack('<BB14I14h', shape_data)
- commands.append(ShapeDrawBitmapCommand(
- texture=self.textures[tex_id],
- xys=((rest[0]/-20, rest[1]/-20),
- (rest[2]/-20, rest[3]/-20),
- (rest[4]/-20, rest[5]/-20),
- (rest[6]/-20, rest[7]/-20),
- (rest[8]/-20, rest[9]/-20),
- (rest[10]/-20, rest[11]/-20),
- (rest[12]/-20, rest[13]/-20)),
- uvs=((rest[14], rest[15]),
- (rest[16], rest[17]),
- (rest[18], rest[19]),
- (rest[20], rest[21]),
- (rest[22], rest[23]),
- (rest[24], rest[25]),
- (rest[26], rest[27]))
- ))
- elif length == 98:
- (tex_id, nothing2, *rest) = struct.unpack('<BB16I16h', shape_data)
- commands.append(ShapeDrawBitmapCommand(
- texture=self.textures[tex_id],
- xys=((rest[0]/-20, rest[1]/-20),
- (rest[2]/-20, rest[3]/-20),
- (rest[4]/-20, rest[5]/-20),
- (rest[6]/-20, rest[7]/-20),
- (rest[8]/-20, rest[9]/-20),
- (rest[10]/-20, rest[11]/-20),
- (rest[12]/-20, rest[13]/-20),
- (rest[14]/-20, rest[15]/-20)),
- uvs=((rest[16], rest[17]),
- (rest[18], rest[19]),
- (rest[20], rest[21]),
- (rest[22], rest[23]),
- (rest[24], rest[25]),
- (rest[26], rest[27]),
- (rest[28], rest[29]),
- (rest[30], rest[31]))
- ))
最后再提几个细节问题,解压lzma需要安装PYLZMA库,然后进行相关调用来解压,当然嫌麻烦也可以直接将改了之后的.sc后缀改成.lzma直接用系统默认工具解压也可。至于scf,需要Pillow库,目前的切图都是矩形去切的,但是自BoomBeach发布以来,SC使用了新的图片打包技术,他可以做到把小图片放在大图片边角的缝隙里,然后打成一张大图,这个技术要比TexturePacker先进,他这么做,也导致了切图不能按照矩形来切,是不规则多边形去切的,这个技术究竟是怎么实现的目前还没有眉目。还有一点,SC的骨骼动画也都放在scf文件里,但是只是用parse_texture是只能获取每个骨骼的图片的,想要得到骨骼动画各个骨骼间的信息,得去解析别的attribute的数据,这个目前没有可参考的内容,如果单纯分析数据内容工作量是极大的。
总而言之,SC的游戏用的都是自己的引擎,而且这个引擎十分强大,为什么SC的游戏资源看着又细腻又多,但是安装包不算大,秘密都在scf里,他的引擎的相关研究我做的也是十分浅薄的,但是我相信值得借鉴的地方很多,有大牛对此有所研究的还望一起交流。
最后贴几张效果图,按照矩形切的。
BB的:
Hayday的:
COC的: