《石器时代》《魔力宝贝》图像压缩格式的破解

这两种游戏使用的是同一种压缩方式,都是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是图像压缩数据文件,一幅图像的结构如下:

typedef  struct
{
    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


有了这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;
}



终于写完了,希望能对别人有用。。。


《魔力宝贝》 《石器时代》 图片破解 补遗


上次分析得不够完善,一些情况没有分析出来,抱歉。下面是补充。

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个颜色的数值。所使用的时候要注意。

暂时就补充这些了。如果需要软件或者原码,请请联系我 [email protected]。 

你可能感兴趣的:(游戏,c,struct,null,存储,破解)