游戏开发论坛

 找回密码
 立即注册
搜索
查看: 1656|回复: 0

剑侠MPC文件的解包程序

[复制链接]

3

主题

186

帖子

190

积分

注册会员

Rank: 2

积分
190
发表于 2004-5-19 17:03:00 | 显示全部楼层 |阅读模式
上次看了WindLucid的文章,就写了一个程序,MPC包是likesmoke给我的,所以不知道具体对于那些版本适用

// ExtractMPC.cpp : 定义控制台应用程序的入口点。
//

// 作    者 : 风舞影天(snwcwt)
// 完成时间 : 二零零四年五月十九日
// 小组网站 : http://www.gamefps.com/

#include "stdafx.h"
#include <iostream>
#include <windows.h>
using namespace std;

struct   MPCPALETE
{
        unsigned        blue        : 8;                // 蓝
        unsigned        green        : 8;                // 绿
        unsigned        red                : 8;                // 红
        unsigned        alpha        : 8;                // Alpha值
};
//图片数据的头结构:
struct   MPCPICDATAHEADER
{
        int                picDataSize;        // 图片数据大小
        int                picWidth;                // 图片宽
        int                picHeight;                // 图片高
        int                NULL1;                        // 0 可能是保留值,设为NULL
        int                NULL2;                        // 0
};
//MPC 图片文件的头结构:
struct  MPCFILEHEADER
{
        char        mpcFlag[16];                        // 标志 "MPC File Ver2.0"
        int                mpcNULL1[12];                        // 0
        int                mpcPicDataSize;                        // 图片数据长度
        int                mpcMaxWidth;                        // 所有图片中最大宽
        int                mpcMaxHeight;                        // 所有图片中最大高
        int                mpcPicCount;                        // 图片数量
        int                mpcPicBitCount;                        // 8 图片象素位数?
        int                mpcPalleteSize;                        //  调色板中颜色索引个数
        int                mpcNull2;                                // 0x64
        int                mpcNull3[9];                        // 保留为0
};

void mpc2bmp( const char* szFileName );
void savebmp(const char *bmpfileName,unsigned char* bmpData,int nDataLen,int nWidth,int nHeight);

int _tmain(int argc, _TCHAR* argv[])
{
        if( argc != 2 )
                std::cout << "请输入MPC文件名。" << std::endl;
        mpc2bmp( argv[1] );
        return 0;
}

void mpc2bmp( const char* szFileName )
{
        FILE*        pFile = NULL;
        char        szBmpFileName[MAX_PATH];

        pFile = fopen( szFileName, "rb" );
        if( pFile == NULL )
        {
                std::cout << "打开文件时出错。" << std::endl;
                return;
        }
        MPCFILEHEADER        fileHeader;
        // 读入MPC文件头
        fread( &fileHeader, sizeof(MPCFILEHEADER), 1, pFile );
        // 创建并读入调色板数据
        MPCPALETE* pPalete = new MPCPALETE[fileHeader.mpcPalleteSize];
        fread( pPalete, sizeof(MPCPALETE), fileHeader.mpcPalleteSize, pFile );
        // 读入所有图片文件的偏移量(相对)
        int* pFileOffset = new int[fileHeader.mpcPicCount];
        fread( pFileOffset, sizeof(int), fileHeader.mpcPicCount, pFile );
        // 循环读入图片数据并保存为BMP图片
        MPCPICDATAHEADER picHeader;                // 图片数据头
        for( int i = 0; i < fileHeader.mpcPicCount; ++i )
        {
                // 读入图片数据头信息
                fread( &picHeader, sizeof(MPCPICDATAHEADER), 1, pFile );
                int iDataLen = picHeader.picDataSize - sizeof(MPCPICDATAHEADER);
                // 分配MPC图片数据缓冲区并读入
                unsigned char* pMpcData = new unsigned char[iDataLen];
                fread( pMpcData, 1, iDataLen, pFile );
                // 分配BMP图数据缓冲区
                int iBmpLen = picHeader.picHeight*( picHeader.picWidth*3+picHeader.picWidth%4 );
                unsigned char* pBmpData = new unsigned char[iBmpLen];
                // 解析图片数据
                int iPos = 0;
                int iBmpPos = 0;
                int iRow = 0;
                int iCol = 0;
                int iNumber = 0;
                while( iPos < iDataLen )
                {
                        if( pMpcData[iPos] > 0x80 )
                        { // 透明色
                                iNumber = pMpcData[iPos]&0x7f;
                                iCol += iNumber;                                                        // 调整列数
                                while( iNumber-- )
                                {
                                        pBmpData[iBmpPos++] = 0xFF;
                                        pBmpData[iBmpPos++] = 0x00;
                                        pBmpData[iBmpPos++] = 0xFF;
                                }
                        }
                        else
                        {
                                iNumber = pMpcData[iPos];                                        // 接下来的iNumber个象素为调色板数据
                                iCol += iNumber;                                                        // 调整列数
                                while( iNumber-- )
                                {
                                        ++iPos;                                                                        // 调整偏移位置
                                        pBmpData[iBmpPos++] = pPalete[pMpcData[iPos]].red;
                                        pBmpData[iBmpPos++] = pPalete[pMpcData[iPos]].green;
                                        pBmpData[iBmpPos++] = pPalete[pMpcData[iPos]].blue;
                                }
                        }
                        if( iCol == picHeader.picWidth )
                        { // 存储一行数据
                                iRow++;
                                iCol = 0;
                                // 填充行尾数据
                                for( int j = 0; j < picHeader.picWidth%4; ++j )
                                {
                                        pBmpData[iBmpPos++] = 0;
                                }
                        }
                        iPos++;
                }
                // 存储图片
                sprintf( szBmpFileName, "%s-%d.bmp", szFileName, i );
                savebmp( szBmpFileName, pBmpData, iBmpLen, picHeader.picWidth, picHeader.picHeight );
                delete[] pMpcData;
                delete[] pBmpData;
        }
        delete[] pFileOffset;
        delete[] pPalete;
        fclose( pFile );
}


void  savebmp(const char *bmpfileName,unsigned char *
                          bmpData,int nDataLen,int nWidth,int nHeight)
{
        FILE                                *bmpFile=NULL;
        BITMAPFILEHEADER        bmpHeader;
        BITMAPINFO                        bmpInfo;
        unsigned char                *tempData;
        int                                        nPitch = nWidth*3+nWidth%4;
        tempData = bmpData+nDataLen-nPitch;
        bmpFile = fopen( bmpfileName, "w+b" );
        if( bmpFile == NULL )
                return ;

        bmpHeader.bfOffBits = 54;
        bmpHeader.bfSize = nDataLen+54;
        bmpHeader.bfType = 19778;         //"BM"
        bmpHeader.bfReserved1 = 0;
        bmpHeader.bfReserved2 = 0;

        bmpInfo.bmiHeader.biSize = 40;
        bmpInfo.bmiHeader.biWidth = nWidth;
        bmpInfo.bmiHeader.biHeight = nHeight;
        bmpInfo.bmiHeader.biPlanes = 1;
        bmpInfo.bmiHeader.biBitCount = 24;
        bmpInfo.bmiHeader.biCompression = 0;
        bmpInfo.bmiHeader.biSizeImage = nDataLen;
        bmpInfo.bmiHeader.biXPelsPerMeter = 3780;
        bmpInfo.bmiHeader.biYPelsPerMeter = 3780;
        bmpInfo.bmiHeader.biClrUsed = 0;
        bmpInfo.bmiHeader.biClrImportant = 0;

        fwrite( &bmpHeader, 1, sizeof(bmpHeader), bmpFile );
        fwrite( &bmpInfo, 1, sizeof(bmpInfo), bmpFile );

        fseek( bmpFile, (-1)*sizeof(bmpInfo.bmiColors), SEEK_CUR );

        for( ; nHeight > 0; --nHeight )
        {
                fwrite( tempData, 1, nPitch, bmpFile );
                tempData -= nPitch;
        }
        fclose( bmpFile );
}
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-7-1 02:05

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表