这两种游戏使用的是同一种压缩方式,都是RLE压缩方式,具体的压缩编码如下:
0a xx xx xx
a 个单独的颜色点
1a bb xx xx xx
abb 个单独的颜色点
Da bb
abb 个透明色
Ca
a 个透明色
8a xx
a 个颜色是XX的点
9a xx bb
abb 个颜色为xx的点
Aa xx bb cc
abbcc 个颜色为xx的点
其他情况,没有压缩
基本上超过3个点一样就用8a xx 了
然后,以魔力宝贝为例,graphics_10.bin是图像压缩数据文件,一幅图像的结构如下:
另外还有一个GraphicInfo_10.bin的文件,里面是图片信息的数据,具体结构如下:
有了这3样资料,就可以从他们的数据文件里面解出我们需要的图片了。
一般来说,他们的图片都是256色的,调色板存储在相应的目录下,只要读出来就能够把颜色调整好。
但是魔力宝贝3。0增加了16位色的新资源,其实,压缩方法还是按照字节的方式来得。只不过,输出的缓存不再是高度* 宽度,而是高度* 宽度的2倍。
而且是两个字节描述一个点的16位色位图。具体是555,还是565模式的,我没有试验。
下面是我的8位解压函数,不过一些情况没有处理,比如说没有压缩的数据。而且写得很烂。。。。。-_-b
如果需要改成16位,需要送进的out_len 是 w * h *2。
终于写完了,希望能对别人有用。。。
《魔力宝贝》 《石器时代》 图片破解 补遗
上次分析得不够完善,一些情况没有分析出来,抱歉。下面是补充。
RLE压缩的地方多了几个:
0a xx xx xx
a 个单独的颜色点
1a bb xx xx xx
abb 个单独的颜色点
(添加)
2a bb cc xx xx xx
abbcc个单独的点
Ca
a 个透明色
Da bb
abb 个透明色
(添加)
Ea bb cc
abbcc个透明色
8a xx
a 个颜色是XX的点
9a xx bb
abb 个颜色为xx的点
Aa xx bb cc
abbcc 个颜色为xx的点
所有的a ,b ,c 都是表示单个十六进制数字
关于3。0的魔力宝贝添加的图片其实还是8位色的图片。按照8位色的图片解出来就是了,她不过是用了16位色的显示模式(其实是任何显示模式都可以)。
还有,《石器时代》的INFO的结构和魔力宝贝一样,不过,需要在后面添加一个40字节的数组,什么用都没有。只是结构增大为80字节。
另外,他们的调色板把前面的16个位置丢掉了,就是说实际上调色板是存储了后236个颜色的数值。所使用的时候要注意。
暂时就补充这些了。如果需要软件或者原码,请请联系我 johndragon@sohu.com。
0a xx xx xx
a 个单独的颜色点
1a bb xx xx xx
abb 个单独的颜色点
Da bb
abb 个透明色
Ca
a 个透明色
8a xx
a 个颜色是XX的点
9a xx bb
abb 个颜色为xx的点
Aa xx bb cc
abbcc 个颜色为xx的点
其他情况,没有压缩
基本上超过3个点一样就用8a xx 了
然后,以魔力宝贝为例,graphics_10.bin是图像压缩数据文件,一幅图像的结构如下:
typedef
struct
... {
WORD fmtflag; //全部为"RD"
WORD unknow; //不知道什么用
DWORD width;
DWORD height;
DWORD size; // 整个结构大小,就是头+压缩数据
unsigned char * pdata; // 大小为(size - 16)
} st_RDHeader;
... {
WORD fmtflag; //全部为"RD"
WORD unknow; //不知道什么用
DWORD width;
DWORD height;
DWORD size; // 整个结构大小,就是头+压缩数据
unsigned char * pdata; // 大小为(size - 16)
} st_RDHeader;
另外还有一个GraphicInfo_10.bin的文件,里面是图片信息的数据,具体结构如下:
typedef
struct
... {
int idx; //索引号,基本上是按照顺序排列的
DWORD fileptr; //在数据文件中的偏移量
DWORD size; //大小,整个图像结构的大小,同上一个结构的SIZE
int ofs_x; //x偏移量
int ofs_y; //y偏移量,就是对齐点离坐上角的y 轴距离
DWORD width;
DWORD height;
DWORD colorkey; //随便猜得,不一定正确
DWORD unuse1;
DWORD unuse2;
} st_GrpInfo; // 40 bytes
... {
int idx; //索引号,基本上是按照顺序排列的
DWORD fileptr; //在数据文件中的偏移量
DWORD size; //大小,整个图像结构的大小,同上一个结构的SIZE
int ofs_x; //x偏移量
int ofs_y; //y偏移量,就是对齐点离坐上角的y 轴距离
DWORD width;
DWORD height;
DWORD colorkey; //随便猜得,不一定正确
DWORD unuse1;
DWORD unuse2;
} st_GrpInfo; // 40 bytes
有了这3样资料,就可以从他们的数据文件里面解出我们需要的图片了。
一般来说,他们的图片都是256色的,调色板存储在相应的目录下,只要读出来就能够把颜色调整好。
但是魔力宝贝3。0增加了16位色的新资源,其实,压缩方法还是按照字节的方式来得。只不过,输出的缓存不再是高度* 宽度,而是高度* 宽度的2倍。
而且是两个字节描述一个点的16位色位图。具体是555,还是565模式的,我没有试验。
下面是我的8位解压函数,不过一些情况没有处理,比如说没有压缩的数据。而且写得很烂。。。。。-_-b
如果需要改成16位,需要送进的out_len 是 w * h *2。
int
_core_uncompress_rle8(
char
*
instream,
int
in_len,
char
*
outstream,
int
out_len )
... {
char rle_code;
int ptr_instream = 0, ptr_outstream = 0;
int i = 0,loopcnt = 0;;
if( instream == NULL || in_len == 0 || outstream == NULL || out_len == 0 || in_len > out_len )
return 0;
while( ptr_instream < in_len )
...{
rle_code = instream[ptr_instream];
ptr_instream ++;
switch( rle_code & 0xf0 )
...{
case 0x00:
loopcnt = rle_code;
for( i = 0;i < loopcnt;i ++ )
...{
outstream[ptr_outstream] = instream[ptr_instream];
ptr_instream ++;
ptr_outstream ++;
}
break;
case 0x10:
loopcnt = (rle_code & 0xf) * 0x100 + instream[ptr_instream];
ptr_instream ++;
for( i = 0;i < loopcnt;i ++ )
...{
outstream[ptr_outstream] = instream[ptr_instream];
ptr_instream ++;
ptr_outstream ++;
}
break;
case 0x80:
loopcnt = rle_code & 0xf;
rle_code = instream[ptr_instream];
ptr_instream ++;
for( i = 0;i < loopcnt;i ++ )
...{
outstream[ptr_outstream] = rle_code;
ptr_outstream ++;
}
break;
case 0x90:
loopcnt = (rle_code & 0xf) * 0x100 + instream[ptr_instream + 1];
rle_code = instream[ptr_instream];
ptr_instream += 2;
for( i = 0;i < loopcnt;i++)
...{
outstream[ptr_outstream] = rle_code;
ptr_outstream ++;
}
break;
case 0xa0:
loopcnt = (rle_code & 0xf) * 0x10000 + instream[ptr_instream + 1] * 0x100 + instream[ptr_instream + 2];
rle_code = instream[ptr_instream];
ptr_instream += 3;
for( i = 0;i < loopcnt;i ++ )
...{
outstream[ptr_outstream] = rle_code;
ptr_outstream ++;
}
break;
case 0xc0:
loopcnt = rle_code & 0xf;
for( i = 0;i < loopcnt;i ++)
...{
outstream[ptr_outstream] = (char)0xff;
ptr_outstream ++;
}
break;
case 0xd0:
loopcnt = (rle_code & 0xf) * 0x100 + instream[ptr_instream];
ptr_instream ++;
for( i = 0;i < loopcnt;i ++ )
...{
outstream[ptr_outstream] = (char)0xff;
ptr_outstream ++;
}
break;
}
ptr_instream ++;
}
return 1;
}
... {
char rle_code;
int ptr_instream = 0, ptr_outstream = 0;
int i = 0,loopcnt = 0;;
if( instream == NULL || in_len == 0 || outstream == NULL || out_len == 0 || in_len > out_len )
return 0;
while( ptr_instream < in_len )
...{
rle_code = instream[ptr_instream];
ptr_instream ++;
switch( rle_code & 0xf0 )
...{
case 0x00:
loopcnt = rle_code;
for( i = 0;i < loopcnt;i ++ )
...{
outstream[ptr_outstream] = instream[ptr_instream];
ptr_instream ++;
ptr_outstream ++;
}
break;
case 0x10:
loopcnt = (rle_code & 0xf) * 0x100 + instream[ptr_instream];
ptr_instream ++;
for( i = 0;i < loopcnt;i ++ )
...{
outstream[ptr_outstream] = instream[ptr_instream];
ptr_instream ++;
ptr_outstream ++;
}
break;
case 0x80:
loopcnt = rle_code & 0xf;
rle_code = instream[ptr_instream];
ptr_instream ++;
for( i = 0;i < loopcnt;i ++ )
...{
outstream[ptr_outstream] = rle_code;
ptr_outstream ++;
}
break;
case 0x90:
loopcnt = (rle_code & 0xf) * 0x100 + instream[ptr_instream + 1];
rle_code = instream[ptr_instream];
ptr_instream += 2;
for( i = 0;i < loopcnt;i++)
...{
outstream[ptr_outstream] = rle_code;
ptr_outstream ++;
}
break;
case 0xa0:
loopcnt = (rle_code & 0xf) * 0x10000 + instream[ptr_instream + 1] * 0x100 + instream[ptr_instream + 2];
rle_code = instream[ptr_instream];
ptr_instream += 3;
for( i = 0;i < loopcnt;i ++ )
...{
outstream[ptr_outstream] = rle_code;
ptr_outstream ++;
}
break;
case 0xc0:
loopcnt = rle_code & 0xf;
for( i = 0;i < loopcnt;i ++)
...{
outstream[ptr_outstream] = (char)0xff;
ptr_outstream ++;
}
break;
case 0xd0:
loopcnt = (rle_code & 0xf) * 0x100 + instream[ptr_instream];
ptr_instream ++;
for( i = 0;i < loopcnt;i ++ )
...{
outstream[ptr_outstream] = (char)0xff;
ptr_outstream ++;
}
break;
}
ptr_instream ++;
}
return 1;
}
终于写完了,希望能对别人有用。。。
《魔力宝贝》 《石器时代》 图片破解 补遗
上次分析得不够完善,一些情况没有分析出来,抱歉。下面是补充。
RLE压缩的地方多了几个:
0a xx xx xx
a 个单独的颜色点
1a bb xx xx xx
abb 个单独的颜色点
(添加)
2a bb cc xx xx xx
abbcc个单独的点
Ca
a 个透明色
Da bb
abb 个透明色
(添加)
Ea bb cc
abbcc个透明色
8a xx
a 个颜色是XX的点
9a xx bb
abb 个颜色为xx的点
Aa xx bb cc
abbcc 个颜色为xx的点
所有的a ,b ,c 都是表示单个十六进制数字
关于3。0的魔力宝贝添加的图片其实还是8位色的图片。按照8位色的图片解出来就是了,她不过是用了16位色的显示模式(其实是任何显示模式都可以)。
还有,《石器时代》的INFO的结构和魔力宝贝一样,不过,需要在后面添加一个40字节的数组,什么用都没有。只是结构增大为80字节。
另外,他们的调色板把前面的16个位置丢掉了,就是说实际上调色板是存储了后236个颜色的数值。所使用的时候要注意。
暂时就补充这些了。如果需要软件或者原码,请请联系我 johndragon@sohu.com。