crass++final源码分析笔记

使用的技术:动态链接库技术:acui_core
所有.cui插件都是dll(x86)文件
Crass是Crage和Assage两个工具的集合。Crage是使用cui插件扩展的游戏资源提取器;而Assage是使用aui插件扩展的游戏资源封装程序。

只要使用cui或aui插件,就可以提取或封装插件所对应的封包文件。

对于普通的使用者,可以使用CrageGUI,通过图形界面进行资源提取;crage也为高级用户提供了控制台程序;有关crage的更多使用说明参见INSTALL.txt;另外document中是每个cui插件的详细信息,解包前应当阅读。

 

【使用crage】
crage有2种使用界面:控制台界面和图形界面。

除了图形界面CrageGUI.exe

建议使用:JCrage(包内自带,运行需要JAVA 虚拟机 JRE)

http://p.blog.csdn.net/images/p_blog_csdn_net/luozhuang/EntryImages/20090925/Jcrage.jpg

 

Crass已经停止开发.......

acui_core.h

acui_core.h
#ifndef ACUI_CORE_H
#define ACUI_CORE_H

#ifdef ACUI_CORE_EXPORTS
#define ACUI_CORE_API __declspec(dllexport)
#else
#define ACUI_CORE_API __declspec(dllimport)
#endif 

extern ACUI_CORE_API int cui_core_init(const TCHAR *cui_dir);
extern ACUI_CORE_API void cui_core_uninstall(void);
extern ACUI_CORE_API struct cui *cui_walk_each(struct cui *cui);
extern ACUI_CORE_API void cui_print_information(struct cui *cui);
extern ACUI_CORE_API struct cui_extension *cui_extension_walk_each(struct cui *cui,
        struct cui_extension *extension, unsigned long flags);
extern ACUI_CORE_API void cui_uninstall(struct cui *cui);
extern ACUI_CORE_API int aui_core_init(const TCHAR *aui_dir);
extern ACUI_CORE_API void aui_core_uninstall(void);
extern ACUI_CORE_API struct aui *aui_walk_each(struct aui *aui);
extern ACUI_CORE_API void aui_print_information(struct aui *aui);
extern ACUI_CORE_API struct aui_extension *aui_extension_walk_each(struct aui *aui,
        struct aui_extension *extension, unsigned long flags);
extern ACUI_CORE_API void aui_uninstall(struct aui *aui);

#endif    /* ACUI_CORE_H */

以Muscia引擎封包格式的每个插件的封包资源释放函数形如

/* 封包资源释放函数 */
static void Musica_dat_release_resource(struct package *pkg, 
                                        struct package_resource *pkg_res)
{
    if (!pkg || !pkg_res)
        return;

    if (pkg_res->actual_data) {
        free(pkg_res->actual_data);
        pkg_res->actual_data = NULL;
    }
    if (pkg_res->raw_data)
        pkg_res->raw_data = NULL;
}
/* 资源保存函数 */
static int Musica_dat_save_resource(struct resource *res, 
                                    struct package_resource *pkg_res)
{
    if (!res || !pkg_res)
        return -CUI_EPARA;
    
    if (res->rio->create(res))
        return -CUI_ECREATE;

    if (pkg_res->actual_data && pkg_res->actual_data_length) {
        if (res->rio->write(res, pkg_res->actual_data, pkg_res->actual_data_length)) {
            res->rio->close(res);
            return -CUI_EWRITE;
        }
    } else if (pkg_res->raw_data && pkg_res->raw_data_length) {
        if (res->rio->write(res, pkg_res->raw_data, pkg_res->raw_data_length)) {
            res->rio->close(res);
            return -CUI_EWRITE;
        }
    }

    res->rio->close(res);
    
    return 0;
}
/* 封包资源提取函数 */
static int Musica_dat_extract_resource(struct package *pkg,
                                       struct package_resource *pkg_res)
{
    BYTE *cipher, *plain;
    BYTE *compr, *uncompr;
    DWORD comprlen, uncomprlen;
    u32 dat_size;

    if (pkg->pio->length_of(pkg, &dat_size))
        return -CUI_ELEN;

    cipher = (BYTE *)pkg->pio->readvec_only(pkg, dat_size, 0, IO_SEEK_SET);
    if (!cipher)
        return -CUI_EREADVECONLY;

    plain = (BYTE *)malloc(dat_size);
    if (!plain)
        return -CUI_EMEM;

    memcpy(plain, cipher, dat_size);
    paz_decrypt((DWORD *)plain, dat_size, (unsigned char *)"minori", 6);

    uncomprlen = *(u32 *)plain;
    comprlen = dat_size - 4;
    compr = plain + 4;

    uncompr = (BYTE *)malloc(uncomprlen);
    if (!uncompr) {
        free(plain);
        return -CUI_EMEM;
    }

    if (uncompress(uncompr, &uncomprlen, compr, comprlen) != Z_OK) {
        free(uncompr);
        free(plain);
        return -CUI_EUNCOMPR;
    }
    free(plain);

    pkg_res->raw_data = cipher;
    pkg_res->raw_data_length = dat_size;
    pkg_res->actual_data = uncompr;
    pkg_res->actual_data_length = uncomprlen;

    return 0;
}
static void paz_decrypt(DWORD *cipher, DWORD cipher_length, unsigned char *key, int key_len)
{
    BLOWFISH_CTX ctx;
    DWORD i;
    
    Blowfish_Init(&ctx, key, key_len);
    for (i = 0; i < cipher_length / 8; i++)
        Blowfish_Decrypt(&ctx, &cipher[i * 2 + 0], &cipher[i * 2 + 1]);
}

引擎调用cui插件的函数和文件:carge/carge.cpp

/* 封包资源释放函数 */
static void cui_common_release_resource(struct package *pkg, 
                                        struct package_resource *pkg_res)
{
    if (pkg_res->actual_data) {
        free(pkg_res->actual_data);
        pkg_res->actual_data = NULL;
    }
    if (pkg_res->raw_data) {
        free(pkg_res->raw_data);
        pkg_res->raw_data = NULL;
    }
}

cui插件核心函数
Crass-source/common/SDK/include/cui.h

Crass-source/common/SDK/include/cui.h
#ifndef CUI_H
#define CUI_H

struct cui_register_callback;

/* cui必须暴露的API原型 */
typedef int (CALLBACK *register_cui_t)(struct cui_register_callback *callback);
//typedef void (CALLBACK *unregister_cui_t)(struct cui_unregister_callback *callback);
typedef void (CALLBACK *show_cui_info_t)(struct acui_information *info);

struct cui_extension;
/* cui信息(cui代码中不要直接操作以下任何成员) */
struct cui {
    struct cui *prev;        /* cui链表的前指针 */
    struct cui *next;        /* cui链表的后指针 */
    HMODULE module;            /* cui模块句柄 */
    TCHAR *name;            /* cui模块名 */
    struct cui_extension *first_ext;
    struct cui_extension *last_ext;        
    unsigned int ext_count;    /* 支持的扩展名数量 */
};

/* cui扩展名信息(cui代码中不要直接操作以下任何成员) */
struct cui_extension {
    struct cui_ext_operation *op;
    const TCHAR *extension;
    const TCHAR *replace_extension;
    const TCHAR *description;
    struct cui_extension *next_ext;
    struct cui *cui;
    unsigned long flags;
};

/* 每个封包扩展名或特定封包名称的操作函数 */
struct cui_ext_operation {
    int (*match)(struct package *);                /* 是否支持该封包 */
    int (*extract_directory)(struct package *,    /* 提取directory数据 */
        struct package_directory *);
    int (*parse_resource_info)(struct package *,/* 解析resource信息 */
        struct package_resource *);    
    int (*extract_resource)(struct package *,    /* 提取资源文件数据 */
        struct package_resource *);    
    int (*save_resource)(struct resource *,        /* 保存资源数据 */
        struct package_resource *);    
    void (*release_resource)(struct package *,    /* 释放相关资源 */
        struct package_resource *);
    void (*release)(struct package *,            /* 释放相关资源 */
        struct package_directory *);
};

/* cui注册时crage提供的回调函数 */
struct cui_register_callback {
    struct cui *cui;
    /* 添加扩展名以支持相应的封包文件。
     * @handle: 操作句柄。
     * @extension: 支持的封包扩展名,以"."开头(大小写不敏感)。
     * @replace_extension: (可选)替换用的扩展名,以"."开头。
     * @description: (可选)封包信息。
     * @operation: 解包过程中使用的各种回调操作。
     * @flags: 属性位段定义。
     *
     * 如果待解的封包是一个包含directory的封包,
     * 那么rep_ext为空。
     * 如果待解的封包是一个不包含directory的封包,
     * 也就说是一个编码资源文件,且含扩展名,那么
     * ext为文件名,且匹配由match()来作。
     */
    int (*add_extension)(struct cui *cui, const TCHAR *extension, 
        const TCHAR *replace_extension, const TCHAR *description,
        struct cui_ext_operation *operation, unsigned long flags);
/* flags位段定义 */
#define CUI_EXT_FLAG_PKG        0x00000001    /* 封包型 */
#define CUI_EXT_FLAG_RES        0x00000002    /* 资源型 */
#define CUI_EXT_FLAG_NOEXT        0x00010000    /* 无扩展名 */
#define CUI_EXT_FLAG_DIR        0x00020000    /* 含目录 */
#define CUI_EXT_FLAG_LST        0x00040000    /* 需要额外的索引文件 */
#define CUI_EXT_FLAG_OPTION        0x00080000    /* 需要获得额外的配置参数 */
#define CUI_EXT_FLAG_NO_MAGIC    0x00100000    /* 没有magic匹配 */
#define CUI_EXT_FLAG_WEAK_MAGIC    0x00200000    /* 尽管没有magic匹配,但是扩展名相对独特 */
//#define CUI_EXT_FLAG_IMPACT        0x00400000    /* 对于magic相同的cui,在extract_dir和extract_resource阶段都不算错误 */
#define CUI_EXT_FLAG_SUFFIX_SENSE    0x00400000    /* 后缀名大小写敏感 */
#define CUI_EXT_FLAG_RECURSION        0x00800000    /* 资源递归处理 */
};

#endif /* CUI_H */

每个插件的封包处理实际函数
AVG32.cpp

/* 封包处理回调函数集合 */
static cui_ext_operation AVG32_KOE_operation = {
    AVG32_KOE_match,                /* match */
    AVG32_KOE_extract_directory,    /* extract_directory */
    AVG32_KOE_parse_resource_info,    /* parse_resource_info */
    AVG32_KOE_extract_resource,        /* extract_resource */
    AVG32_SEEN_save_resource,        /* save_resource */
    AVG32_KOE_release_resource,        /* release_resource */
    AVG32_SEEN_release                /* release */
};
static int AVG32_KOE_extract_directory(struct package *pkg,
                                       struct package_directory *pkg_dir)
{
    KOE_header_t KOE_header;

    if (pkg->pio->readvec(pkg, &KOE_header, sizeof(KOE_header), 0, IO_SEEK_SET))
        return -CUI_EREADVEC;

    if (!KOE_header.rate)
        KOE_header.rate = 22050;

    DWORD table_size = KOE_header.table_len * sizeof(KOE_table_t);
    KOE_table_t *table = (KOE_table_t *)malloc(table_size);
    if (!table)
        return -CUI_EMEM;

    if (pkg->pio->read(pkg, table, table_size)) {
        free(table);
        return -CUI_EREAD;
    }

    DWORD index_buffer_len = KOE_header.table_len * sizeof(KOE_table_t);
    if (!table)
        return -CUI_EMEM;

    DWORD KOE_info_length = KOE_header.table_len * sizeof(KOE_info_t);
    KOE_info_t *KOE_info = (KOE_info_t *)malloc(KOE_info_length);
    if (!KOE_info) {
        free(table);
        return -CUI_EMEM;
    }

    for (DWORD i = 0; i < KOE_header.table_len; i++) {
        sprintf(KOE_info[i].name, "%05d", table[i].koe_num);
        KOE_info[i].length = table[i].length;
        KOE_info[i].offset = table[i].offset;
    }

    pkg_dir->index_entries = KOE_header.table_len;
    pkg_dir->directory = KOE_info;
    pkg_dir->directory_length = KOE_info_length;
    pkg_dir->index_entry_length = sizeof(KOE_info_t);
//    pkg_dir->flags = PKG_DIR_FLAG_SKIP0;
    package_set_private(pkg, KOE_header.rate);

    return 0;
}
/* 接口函数: 向cui_core注册支持的封包类型 */
int CALLBACK AVG32_register_cui(struct cui_register_callback *callback)
{
    if (callback->add_extension(callback->cui, _T(".PDT"), _T(".BMP"), 
        NULL, &AVG32_PDT_operation, CUI_EXT_FLAG_PKG | CUI_EXT_FLAG_RES))
            return -1;

    if (callback->add_extension(callback->cui, _T(".PDT"), _T(".BMP"), 
        NULL, &AVG32_PDT11_operation, CUI_EXT_FLAG_PKG | CUI_EXT_FLAG_RES))
            return -1;

    if (callback->add_extension(callback->cui, _T(".TXT"), NULL, 
        NULL, &AVG32_SEEN_operation, CUI_EXT_FLAG_PKG | CUI_EXT_FLAG_DIR))
            return -1;

    if (callback->add_extension(callback->cui, _T(".CGM"), _T(".CGM_"), 
        NULL, &AVG32_CGM_operation, CUI_EXT_FLAG_PKG))
            return -1;

    if (callback->add_extension(callback->cui, _T(".KOE"), _T(".WAV"), 
        NULL, &AVG32_KOE_operation, CUI_EXT_FLAG_PKG | CUI_EXT_FLAG_DIR))
            return -1;

    return 0;
}

重要cui.h

#ifndef CUI_H
#define CUI_H

struct cui_register_callback;

/* cui必须暴露的API原型 */
typedef int (CALLBACK *register_cui_t)(struct cui_register_callback *callback);
//typedef void (CALLBACK *unregister_cui_t)(struct cui_unregister_callback *callback);
typedef void (CALLBACK *show_cui_info_t)(struct acui_information *info);

struct cui_extension;
/* cui信息(cui代码中不要直接操作以下任何成员) */
struct cui {
    struct cui *prev;        /* cui链表的前指针 */
    struct cui *next;        /* cui链表的后指针 */
    HMODULE module;            /* cui模块句柄 */
    TCHAR *name;            /* cui模块名 */
    struct cui_extension *first_ext;
    struct cui_extension *last_ext;        
    unsigned int ext_count;    /* 支持的扩展名数量 */
};

/* cui扩展名信息(cui代码中不要直接操作以下任何成员) */
struct cui_extension {
    struct cui_ext_operation *op;
    const TCHAR *extension;
    const TCHAR *replace_extension;
    const TCHAR *description;
    struct cui_extension *next_ext;
    struct cui *cui;
    unsigned long flags;
};

/* 每个封包扩展名或特定封包名称的操作函数 */
struct cui_ext_operation {
    int (*match)(struct package *);                /* 是否支持该封包 */
    int (*extract_directory)(struct package *,    /* 提取directory数据 */
        struct package_directory *);
    int (*parse_resource_info)(struct package *,/* 解析resource信息 */
        struct package_resource *);    
    int (*extract_resource)(struct package *,    /* 提取资源文件数据 */
        struct package_resource *);    
    int (*save_resource)(struct resource *,        /* 保存资源数据 */
        struct package_resource *);    
    void (*release_resource)(struct package *,    /* 释放相关资源 */
        struct package_resource *);
    void (*release)(struct package *,            /* 释放相关资源 */
        struct package_directory *);
};

/* cui注册时crage提供的回调函数 */
struct cui_register_callback {
    struct cui *cui;
    /* 添加扩展名以支持相应的封包文件。
     * @handle: 操作句柄。
     * @extension: 支持的封包扩展名,以"."开头(大小写不敏感)。
     * @replace_extension: (可选)替换用的扩展名,以"."开头。
     * @description: (可选)封包信息。
     * @operation: 解包过程中使用的各种回调操作。
     * @flags: 属性位段定义。
     *
     * 如果待解的封包是一个包含directory的封包,
     * 那么rep_ext为空。
     * 如果待解的封包是一个不包含directory的封包,
     * 也就说是一个编码资源文件,且含扩展名,那么
     * ext为文件名,且匹配由match()来作。
     */
    int (*add_extension)(struct cui *cui, const TCHAR *extension, 
        const TCHAR *replace_extension, const TCHAR *description,
        struct cui_ext_operation *operation, unsigned long flags);
/* flags位段定义 */
#define CUI_EXT_FLAG_PKG        0x00000001    /* 封包型 */
#define CUI_EXT_FLAG_RES        0x00000002    /* 资源型 */
#define CUI_EXT_FLAG_NOEXT        0x00010000    /* 无扩展名 */
#define CUI_EXT_FLAG_DIR        0x00020000    /* 含目录 */
#define CUI_EXT_FLAG_LST        0x00040000    /* 需要额外的索引文件 */
#define CUI_EXT_FLAG_OPTION        0x00080000    /* 需要获得额外的配置参数 */
#define CUI_EXT_FLAG_NO_MAGIC    0x00100000    /* 没有magic匹配 */
#define CUI_EXT_FLAG_WEAK_MAGIC    0x00200000    /* 尽管没有magic匹配,但是扩展名相对独特 */
//#define CUI_EXT_FLAG_IMPACT        0x00400000    /* 对于magic相同的cui,在extract_dir和extract_resource阶段都不算错误 */
#define CUI_EXT_FLAG_SUFFIX_SENSE    0x00400000    /* 后缀名大小写敏感 */
#define CUI_EXT_FLAG_RECURSION        0x00800000    /* 资源递归处理 */
};

#endif /* CUI_H */

 

posted on 2025-12-23 13:04  小沙盒工作室  阅读(1)  评论(0)    收藏  举报