0x00 CR的图片资源是在SC文件夹中 一般为XXX_tex.sc
sc文件是一个压缩文件,它是使用了修改的LZMA压缩算法进行压缩的(和老版的COC资源压缩方法类似)
标准的LZMA压缩文件的文件头由5+8个字节组成,其中前5个字节中存储了压缩方式,字典大小等信息,后8个字节为压缩前的文件大小;COC所使用的修改后的LZMA算法,其文件头由5+4个字节组成,跟标准算法相比,仅仅是将表示压缩前的文件大小那8个字节,改成了4个字节
如果要使用标准LZMA算法的解压工具能正确解压COC中的资源,只要在第9个字节后面插入4个0字节,
如上图SC文件,其前26个字节是SC文件头信息, 紧接着的13个字节如下:
0x5D 0x00 0x00 0x04 0x00 0x59 0xD9 0x94 0x00 0x00 0x00 0xB1 0xBA
在第9个字节后插入4个0字节,得到如下格式:
0x5D 0x00 0x00 0x04 0x00 0x59 0xD9 0x94 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xB1 0xBA
然后可以用LZMA类库 进行解压缩
0x01 解压后的文件我们暂且称为scf文件
scf文件前5个字节是文件信息,它的结构如下:
类型1 | 长度1 | 数据块1 |
类型2 | 长度2 | 数据块2 |
... | ... | ... |
类型n | 长度n | 数据块n |
其中:类型为1个字节,标识数据块是何类型;长度为4个字节,表示随后的数据块的字节长度。
类型1是纹理(texture),类型2是shape,类型3是movie_clip.....这里只研究Tuxture,其他的类型感兴趣的可自己研究
纹理(texture)其数据块结构如下:
纹理格式 | 纹理宽度 | 纹理高度 | 纹理数据 |
其中:格式为1个字节,宽度为2个字节,高度为2个字节。
格式为0是RGBA8888格式(32位)
格式为2是RGBA4444格式(16位)
格式为4是RGB565格式(16位)
格式为6是LA88格式(16位)
我用Python 写了个提取脚本ExtractRes.py,里面的LA88灰度算法我不是太确定(但影响也不是太大),
用法 python ExtractRes.py xxx/sc (这里的sc是资源文件夹)
注意安装PyLZMA 和 Pillow 这两个库
PyLZMA https://pypi.python.org/pypi/pylzma
Pillow https://pypi.python.org/pypi/Pillow/
# 皇室战争图片资源提取 By:BlueEffie
# 需要安装2个库
# PyLZMA https://pypi.python.org/pypi/pylzma
# Pillow https://pypi.python.org/pypi/Pillow/
import os
import sys
import pylzma
import struct
import PIL.Image
if len(sys.argv) != 2:
print('Usage: ./ExtractRes.py [SC_Directory]')
exit(0)
class PixelType:
rgba8888 = 0
rgba4444 = 2
rgb565 = 4
la88 = 6
def extract_sc_files(path):
for root, dirs, files in os.walk(path):
for name in files:
if name.endswith('.sc'):
lzma_decompress(root, name)
# 解压缩
def lzma_decompress(path, name):
data = os.path.join(path, name)
filename, exc = os.path.splitext(name)
with open(data, 'rb') as fin:
fin.seek(26, 0)
header = fin.read(5)
raw_size = fin.read(4)
size = struct.unpack('> 12) & 15) << 4, ((x >> 8) & 15) << 4, ((x >> 4) & 15) << 4, ((x >> 0) & 15) << 4)
return r, g, b, a
elif bmp_type == PixelType.rgb565:
x, = struct.unpack('> 11) & 31) << 3, ((x >> 5) & 63) << 2, (x & 31) << 3
elif bmp_type == PixelType.la88:
x, = struct.unpack('