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 */
浙公网安备 33010602011771号