架构理念:[简单][高效][可依赖] 管理理念:[价值][勇气][专注]

jxqy1 unpack

Mignet/Jx: jx (github.com)

debug模式需要添加c++

..\..\Engine\Include;%(AdditionalIncludeDirectories)

 

// PackSingle.cpp : Defines the entry point for the console application.
//

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <direct.h>
#include <sstream>
//首先是处理SPR文件的代码

//SPR头文件的定义,为了实现可移植的目标


#include "ZPackFile.h"
typedef struct {
    BYTE    Comment[4];    // 注释文字(SPR\0)
    WORD    Width;        // 图片宽度
    WORD    Height;        // 图片高度
    WORD    CenterX;    // 重心的水平位移
    WORD    CenterY;    // 重心的垂直位移
    WORD    Frames;        // 总帧数
    WORD    Colors;        // 颜色数
    WORD    Directions;    // 方向数
    WORD    Interval;    // 每帧间隔(以游戏帧为单位)
    WORD    Reserved[6];// 保留字段(到以后使用)
} SPRHEAD;

typedef struct
{
    DWORD    Offset;        // 每一帧的偏移
    DWORD    Length;        // 每一帧的长度
} SPROFFS;


//重新定义
#define FRAME_SIZE            800 * 1024            //800K以上的SPR文件使用分帧的压缩
int root_length = 0;

#define MAX_FILE                    2004800            //最多20万个文件

index_info index_list[MAX_FILE];
char *temp_buffer[MAX_FILE * sizeof(index_info)];
int file_count;                                        //当前文件的数量

unsigned long offset;                                //当前偏移量
#define COMPRESS_BUF_SIZE    10240000
char compress_buffer[COMPRESS_BUF_SIZE];            //10M的压缩缓冲区,存放所有的帧,一次写

#include <ucl/ucl.h>
bool bCheck = false;
#include <conio.h>

//增加一个文件到数据文件中,返回偏移量
bool addFile(FILE *output, const char *file_name) {
    char full_name[MAX_PATH];
    getcwd(full_name, MAX_PATH);
    strcat(full_name, "\\");
    strcat(full_name, file_name);
    char *ptr = full_name;
    while(*ptr) {
        if(*ptr >= 'A' && *ptr <= 'Z') *ptr += 'a' - 'A';
        ptr++;
    }

    unsigned long id = hash(full_name + root_length);//0x12345678
    char *to = (char*)malloc(strlen(full_name) - root_length - 13);
    strncpy(to, full_name + root_length+10, strlen(full_name)- root_length -14);
    to[strlen(full_name) - root_length - 14] = '\0';

    id = std::stoul(to, nullptr, 0);
    int index;
    for(index = 0; index < file_count; index++) {
        if(id < index_list[index].id) {
            memmove(temp_buffer, (char *)&index_list[index], (file_count - index) * sizeof(index_info));
            memmove((char *)&index_list[index + 1], temp_buffer, (file_count - index) * sizeof(index_info));
            break;
        }
        else if(id == index_list[index].id) {
            printf("error %s has the same id %d\n", full_name + root_length, id);

            if(!bCheck) exit(0);
            else getch();
        }
    }
    file_count++;
    if(bCheck) {
        printf("check %s ok\n", full_name + root_length);
        return true;
    }

    ZMapFile map(file_name);
    int compress_size = 0;

    unsigned long compress_type = TYPE_UCL;                //使用UCL压缩

    bool bSPR = false;                                    //是否为SPR文件
    const char *ext = file_name + strlen(file_name) - 3;
    if(*ext == 's' && *(ext + 1) == 'p' && *(ext + 2) == 'r') bSPR = true;

    int r;
    unsigned int size = 0;
    map.map();
    if(map.m_Ptr) {

        index_list[index].id = id;
        index_list[index].offset = offset;
        index_list[index].size = map.m_Size;

        ptr = compress_buffer;
        if(!bSPR || map.m_Size < FRAME_SIZE) {
            if(compress_type == TYPE_UCL) {
                r = ucl_nrv2b_99_compress((BYTE *)map.m_Ptr, map.m_Size, (BYTE *)ptr, (unsigned int *)&index_list[index].compress_size, NULL, 5, NULL, NULL);
            }
            else if(compress_type == TYPE_BZIP2) {
//                index_list[index].compress_size = COMPRESS_BUF_SIZE;
//                r = BZ2_bzBuffToBuffCompress(ptr, (unsigned int *)&index_list[index].compress_size, map.m_Ptr, map.m_Size, 9, 0, 30);
            }
            if(r) return false;
            fwrite(compress_buffer, 1, index_list[index].compress_size, output);
            offset += index_list[index].compress_size;
            printf("%s [%d]->[%d]\n", full_name + root_length, map.m_Size, index_list[index].compress_size);
            index_list[index].compress_size |= (compress_type << 24);
        }
        else {                                //每帧独立压缩
            SPRHEAD *head;
            head = (SPRHEAD *)map.m_Ptr;
            memmove(ptr, head, sizeof(SPRHEAD) + head->Colors * 3);            //前面的数据不压缩
            ptr += sizeof(SPRHEAD) + head->Colors * 3;
            frame_info *compress_frame_info = (frame_info *)ptr;                    //压缩后每一帧的数据
            ptr += head->Frames * sizeof(SPROFFS);
    
            SPROFFS *frame_info = (SPROFFS *)(map.m_Ptr + sizeof(SPRHEAD) + head->Colors * 3);        //原来每一帧的数据
            char *frame_data = (char *)frame_info + head->Frames * sizeof(SPROFFS);
            int frame_index;

            int frame_offset = 0;
            for(frame_index = 0; frame_index < head->Frames; frame_index++) {
//压缩每一帧的内容
                if(frame_info[frame_index].Length >= 256) {                //小于256字节的不压缩
                    if(compress_type == TYPE_UCL) {
                        r = ucl_nrv2b_99_compress((BYTE *)frame_data + frame_info[frame_index].Offset, frame_info[frame_index].Length, (BYTE *)ptr, &size, NULL, 10, NULL, NULL);
                    }
                    else if(compress_type == TYPE_BZIP2) {
//                        size = COMPRESS_BUF_SIZE;
//                        r = BZ2_bzBuffToBuffCompress(ptr, &size, frame_data + frame_info[frame_index].Offset, frame_info[frame_index].Length, 9, 0, 30);
                    }
                    if(r) return false;
                    compress_frame_info[frame_index].size = frame_info[frame_index].Length;        //记录原来的大小
                }
                else {
                    size = frame_info[frame_index].Length;
                    memmove(ptr, (BYTE *)frame_data + frame_info[frame_index].Offset, size);
                    compress_frame_info[frame_index].size = -(long)frame_info[frame_index].Length;        //记录原来的大小
                }
                compress_size += size;
                compress_frame_info[frame_index].compress_size = size;
                frame_offset += size;
                ptr += size;        
            }
            fwrite(compress_buffer, 1, ptr - compress_buffer, output);
            offset += ptr - compress_buffer;
            printf("[frame] %s old size = %d, compressed size = %d\n", full_name + root_length, map.m_Size, compress_size);
            index_list[index].compress_size = (ptr - compress_buffer) | ((compress_type | TYPE_FRAME) << 24);
        }
    }
    return true;
}

void addDirectory(FILE *output, const char *rootDir, const char *subDir = NULL) {
    char            szRealDir[MAX_PATH];
    if(subDir) sprintf(szRealDir, "%s\\%s", rootDir, subDir);
    else {
        strcpy(szRealDir, rootDir);
        root_length = strlen(rootDir);
        while(rootDir[root_length] != '\\') root_length--;
    }
    if(chdir(szRealDir)) return;
    _finddata_t FindData;
    long dir = _findfirst("*.*", &FindData);
    while(dir != -1) {
        if(strcmp(FindData.name, ".") == 0 || strcmp(FindData.name, "..") == 0)    {
            if(_findnext(dir, &FindData)) break;
            continue;
        }
        if(FindData.attrib & _A_SUBDIR)
        {
            addDirectory(output, szRealDir, FindData.name);
        }
        else
        {    
            if(!addFile(output, FindData.name)) return;
        }
        if(_findnext(dir, &FindData)) break;
    } 
    _findclose(dir);
    chdir(rootDir);
}

bool pack(const char *dir, const char *pack_name = 0) {
    char name_buffer[MAX_PATH];
    file_count = 0;
    offset = 0;
    if(!pack_name) {
        strcpy(name_buffer, dir);
        strcat(name_buffer, ".pak");
        pack_name = name_buffer;
    }
    FILE * output = NULL;
    z_pack_header header;
    if(!bCheck) {
        output = fopen(pack_name, "wb");
        memset(&header, 0, sizeof(header));
        fwrite(&header, 1, sizeof(header), output);
        offset += sizeof(header);
    }

    char aAddDir[MAX_PATH];
    strcpy(aAddDir, dir);
    strcat(aAddDir, "\\Font");
    addDirectory(output, aAddDir);                    //压缩指定目录
    strcpy(aAddDir, dir);
    strcat(aAddDir, "\\Maps");
    addDirectory(output, aAddDir);                    //压缩指定目录
    strcpy(aAddDir, dir);
    strcat(aAddDir, "\\settings");
    addDirectory(output, aAddDir);                    //压缩指定目录
    strcpy(aAddDir, dir);
    strcat(aAddDir, "\\script");
    addDirectory(output, aAddDir);                    //压缩指定目录
    strcpy(aAddDir, dir);
    strcat(aAddDir, "\\Spr");
    addDirectory(output, aAddDir);                    //压缩指定目录
    strcpy(aAddDir, dir);
    strcat(aAddDir, "\\Sound");
    addDirectory(output, aAddDir);                    //压缩指定目录
    strcpy(aAddDir, dir);
    strcat(aAddDir, "\\Ui");
    addDirectory(output, aAddDir);                    //压缩指定目录
    strcpy(aAddDir, dir);
    strcat(aAddDir, "\\游戏资源");
    addDirectory(output, aAddDir);                    //压缩指定目录

    if(!bCheck) {
        memset(&header, 0, sizeof(header));
        memcpy(header.signature, "PACK", 4);
        header.index_offset = offset;
        header.data_offset = sizeof(header);
        header.count = file_count;
        int result = fwrite(&index_list[0], 1, file_count * sizeof(index_info), output);
        fseek(output, 0, SEEK_SET);
        fwrite(&header, 1, sizeof(header), output);
        fclose(output);
    }
    return true;
}

int main(int argc, char **argv) {

    if(argc < 2) {
        printf("usage: packSingle [pack directory] [pack file name] [/c]\nwithout [pack file name], the pack file name will be the same of directory name\n/c to check the same id\n");
        return 0;
    }

    if (ucl_init() != UCL_E_OK) return 0;

    if(argc > 2) {
        if(!stricmp(argv[2], "/c")) {
            bCheck = true;
            pack(argv[1]);
        }
        else {
            if(argc > 3) {
                if(!stricmp(argv[3], "/c")) bCheck = true;
            }
            pack(argv[1], argv[2]);
        }
    }
    else pack(argv[1]);

    return 0;
}
//首先是处理SPR文件的代码

//SPR头文件的定义,为了实现可移植的目标
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <direct.h>
#include <IOSTREAM>
#include <conio.h>
#include "ZPackFile.h"
#include "SavePack.h"
#include <sstream>

using namespace std;
#define MAX_FILE                    2004800            //最多20万个文件

index_info index_list[MAX_FILE];
char temp_buffer[MAX_FILE * sizeof(index_info)];

void IndexNT2Normal(index_info_nt* IndexNT, index_info* aIndex)
{
    aIndex->id = IndexNT->id;
    aIndex->offset = IndexNT->offset;
    aIndex->size = IndexNT->size;
    aIndex->compress_size = IndexNT->compress_size;
    return;
}
bool PackExp(char* baseFile, char* addFile, char* nowFile, char* saveFile)
{
    //打开四个文件
    ZCache baseCache(65536 * 1024);
    ZPackFileNT basePack(baseFile, &baseCache);
    cout<<"Open Base Pack "<<baseFile<<" Successfully.";
    cout<<"Base Pack File Count:"<<basePack.getFileCount()<<endl;

    ZCache addCache(65536 * 1024);
    ZPackFileNT addPack(addFile, &addCache);
    if(addFile)
    {
        cout<<"Open Add Pack "<<addFile<<" Successfully.";
        cout<<"Add Pack File Count:"<<addPack.getFileCount()<<endl;
    }
    else
    {
        cout<<"No Add Pack File"<<endl;
    }
    
    ZCache nowCache(65536 * 1024);
    ZPackFileNT nowPack(nowFile, &nowCache);
    cout<<"Open Latest Pack "<<nowFile<<" Successfully.";
    cout<<"Latest Pack File Count:"<<nowPack.getFileCount()<<endl;

    CSavePack SavePack;
    if(SavePack.open(saveFile, index_list))
        cout<<"Open Save Pack "<<saveFile<<" Successfully."<<endl;
    else
    {
        cout<<"Error Save Pack "<<saveFile<<" ."<<endl;
        getch();
        exit(1);
    }
    //cout<<"Press any key to continue..."<<endl;
    //getch();
    
    int i;
    for(i=0;i<nowPack.getFileCount();++i)
    {
        index_info_nt* IndexInfoNow = nowPack.IndexData(i);
        
        if(addFile)    //如果addFile里面有这个文件
        {                                    //就跟addFile的这个文件比较时间
            int addPackIndex = addPack.getNodeIndex(IndexInfoNow->id);
            if(addPackIndex != -1)
            {
                index_info_nt* IndexInfoAdd=addPack.IndexData(i);
                if(CompareFileTime(&IndexInfoNow->UpdateTime,&IndexInfoAdd->UpdateTime) != 1)
                {//如果时间与原来的文件一样的话就跳过
                    cout<<"ID:"<<IndexInfoNow->id<<" Skip."<<endl;
                    continue;
                }
            }
        }
        index_info aIndex;
        IndexNT2Normal(IndexInfoNow,&aIndex);
        char* aData = nowPack.getOrigData(IndexInfoNow->id);
        SavePack.AddData(aData, &aIndex, temp_buffer);
        int fileSize = IndexInfoNow->compress_size & 0x00FFFFFF;
        cout<<"Add Data From File:["<<nowFile<<"] ID:"<<IndexInfoNow->id
                <<" Size:"<<fileSize<<endl;
    }
    if(SavePack.Close())
        cout<<"File "<<saveFile<< " Saved."<<endl;
    else
        cout<<"Error Save File "<<saveFile<< " ."<<endl;

    return true;
}

int main(int argc, char **argv)
{

    if(argc < 5) {
        if (argc >= 1) {
            char* basePackFile = argv[1];
            cout << "Press any key to begin test..." << endl;
            getch();
            ZCache aaCache(65536 * 1024);
            ZPackFile aaPack(basePackFile, &aaCache);
            int i;
            const z_pack_header* header = aaPack.GetHeader();
            cout << "Pack File Count:" << aaPack.getFileCount() << endl;

            getch();

            for (i = 0; i < header->count; ++i)
            {
                index_info* IndexInfo = aaPack.IndexData(i);
                int fileSize = IndexInfo->compress_size & 0x00FFFFFF;
                cout << "[" << i << "]||id:"
                    << IndexInfo->id << "||offset:"
                    << IndexInfo->offset << "||compress_size:"
                    << IndexInfo->compress_size << "||size:"
                    << IndexInfo->size << "||fileSize:"
                    << fileSize << "||";

                char* aa = aaPack.getData(IndexInfo->id);//getOrigData
                char* bb = aaPack.getOrigData(IndexInfo->id);//getOrigData
                if (aa == bb) {
                    cout << "getData == getOrigData" << endl;
                }
                if (aa) {
                    FILE *infile;
                    //cout << bb << endl;
                    if (*bb=='S' && (*bb+1) == 'P'&& (*bb+2) == 'R') {
                        cout << "SPR Ready?" << endl;
                    }
                    else {
                        cout << "Other Ready?" << endl;
                    }

                    getch();
                    //SPR
                    if (*bb == 'S' && (*bb + 1) == 'P' && (*bb + 2) == 'R') {
                        infile = fopen((std::to_string(IndexInfo->id) + ".spr").c_str(), "wb");//用fopen函数打开文件
                        if (!infile) {
                            printf("open infile failed....\n");
                            continue;
                        }
                        fwrite(aa, sizeof(char), strlen(aa), infile);//写入内容
                        if (fclose(infile)) {
                            printf("write infile failed....\n");
                        };
                    }
                    else {
                        infile = fopen((std::to_string(IndexInfo->id)+".lua").c_str(), "w");//用fopen函数打开文件
                        if (!infile) {
                            printf("open infile failed....\n");
                            continue;
                        }

                        fprintf(infile, "%s", aa);
                        //fwrite(&aa, 1, count, infile);//写入内容
                        //fputs(aa, infile);
                        if (fclose(infile)) {
                            printf("write infile failed....\n");
                        };
                    }
                    
                    //cout << aa << endl;
                    cout << "OK" << endl;
                    //getch();
                }
                else
                {
                    cout << "Error" << endl;
                    getch();
                }
            }
            getch();
            return 0;

        }
        printf("usage: PackExp [base pack file] [previous version pack file] [present version pack file] [output pack file].\n");
        return 0;
    }

    if (ucl_init() != UCL_E_OK) return 0;

    //argv[1] ----- f:\\temp\\PackBase.pac
    //argv[2] ----- f:\\temp\\PackUpdate1.pac
    //argv[3] ----- f:\\temp\\PackUpdate2.pac
    //argv[4] ----- f:\\temp\\Update1-2.pak

    //生成从版本a到版本b的升级包
    char* basePackFile = argv[1];        //版本0的文件(原始版本)
    char* addPackFile = argv[2];        //版本a的文件
    char* nowPackFile = argv[3];        //版本b的文件
    char* outputPackFile = argv[4];        //导出的文件
    if (strcmp(addPackFile,"none") == 0) addPackFile =NULL;
    PackExp(basePackFile,addPackFile,nowPackFile,outputPackFile);

    if(argc == 5)return 0;
    
    cout<<"Press any key to begin test..."<<endl;
    getch();
    ZCache aaCache(65536 * 1024);
    ZPackFile aaPack(outputPackFile, &aaCache);
    int i;
    const z_pack_header* header = aaPack.GetHeader();
    cout<<"Pack File Count:"<<aaPack.getFileCount()<<endl; 

    getch();
    
    for(i=0;i<header->count;++i)
    {
        index_info* IndexInfo=aaPack.IndexData(i);
        int fileSize = IndexInfo->compress_size & 0x00FFFFFF;
        cout<<"["<<i<<"]||"
            <<IndexInfo->id<<"||"
            <<IndexInfo->offset<<"||"
            <<IndexInfo->size<<"||"
            <<fileSize<<"||";
        char* aa = aaPack.getOrigData(IndexInfo->id);
        if(aa)
            cout<<"OK"<<endl;
        else
        {
            cout<<"Error"<<endl;
            getch();
        }
    }
    getch();
    return 0;
}

 

posted @ 2020-12-25 17:52  文和-Mignet  阅读(339)  评论(0编辑  收藏  举报