/* --------------------------------------- 创建文字绘制对象 (GDI 字体) --------------------------------------- */ static bool_t qst_crh_winfont ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { leng_t len; LOGFONTA font; CR_NOUSE(parm); /* 参数解析 <Height> <FaceName> [Weight] [Width] [CharSet] [Quality] [Italic] [Underline] [StrikeOut] [Escapement] [Orientation] */ if (argc < 3) return (FALSE); if (s_gdi_calls == NULL) return (FALSE); /* 填充字体生成结构 */ struct_zero(&font, LOGFONTA); font.lfCharSet = DEFAULT_CHARSET; font.lfQuality = ANTIALIASED_QUALITY; font.lfHeight = (LONG)str2intxA(argv[1]); if ((len = str_lenA(argv[2])) >= LF_FACESIZE) len = LF_FACESIZE - 1; chr_cpyA(font.lfFaceName, argv[2], len); if (argc > 3) font.lfWeight = (LONG)str2intxA(argv[3]); if (argc > 4) font.lfWidth = (LONG)str2intxA(argv[4]); if (argc > 5) font.lfCharSet = (BYTE)str2intxA(argv[5]); if (argc > 6) font.lfQuality = (BYTE)str2intxA(argv[6]); if (argc > 7) font.lfItalic = (BYTE)str2intxA(argv[7]); if (argc > 8) font.lfUnderline = (BYTE)str2intxA(argv[8]); if (argc > 9) font.lfStrikeOut = (BYTE)str2intxA(argv[9]); if (argc > 10) font.lfEscapement = (LONG)str2intxA(argv[10]); if (argc > 11) font.lfOrientation = (LONG)str2intxA(argv[11]); /* 生成文字输出对象 */ if (s_font != NULL) CR_VCALL(s_font)->release(s_font); s_font = s_gdi_calls->create_fontA(&font); if (s_font == NULL) return (FALSE); return (TRUE); }
/* ======================================= 生成 FB 图形绘制接口 ======================================= */ CR_API iGFX2_FB* create_fb_canvas ( __CR_IN__ const ansi_t* fb ) { iGFX2_FB* rett; /* 创建对象 */ rett = struct_new(iGFX2_FB); if (rett == NULL) return (NULL); struct_zero(&rett->__back__, sIMAGE); /* 初始化 FB */ if (fb == NULL) fb = "/dev/fb0"; rett->m_file = open(fb, O_RDWR); if (rett->m_file < 0) return (NULL); if (ioctl(rett->m_file, FBIOGET_FSCREENINFO, &rett->m_finfo) < 0) goto _failure; if (ioctl(rett->m_file, FBIOGET_VSCREENINFO, &rett->m_vinfo) < 0) goto _failure; if (rett->m_vinfo.bits_per_pixel <= 8 || rett->m_vinfo.red.msb_right || rett->m_vinfo.green.msb_right || rett->m_vinfo.blue.msb_right) goto _failure; /* 填充参数结构 */ rett->__back__.bpl = rett->m_finfo.line_length; if (rett->__back__.bpl % 16 == 0) rett->__back__.align = 16; else if (rett->__back__.bpl % 8 == 0) rett->__back__.align = 8; else if (rett->__back__.bpl % 4 == 0) rett->__back__.align = 4; rect_set_wh(&rett->__back__.clip_win, 0, 0, rett->m_vinfo.xres, rett->m_vinfo.yres); struct_cpy(&rett->__back__.position, &rett->__back__.clip_win, sRECT); rett->__back__.size = rett->__back__.bpl; rett->__back__.size *= rett->m_vinfo.yres; /* 识别颜色格式 */ if (rett->m_vinfo.bits_per_pixel == 16) { if (rett->m_vinfo.red.length == 5 && rett->m_vinfo.green.length == 6 && rett->m_vinfo.blue.length == 5 && rett->m_vinfo.red.offset == 11 && rett->m_vinfo.green.offset == 5 && rett->m_vinfo.blue.offset == 0) { rett->__back__.fmt = CR_ARGB565; rett->__vptr__ = &s_img16_vtbl; } else if (rett->m_vinfo.red.length == 5 && rett->m_vinfo.green.length == 5 && rett->m_vinfo.blue.length == 5 && rett->m_vinfo.red.offset == 10 && rett->m_vinfo.green.offset == 5 && rett->m_vinfo.blue.offset == 0) { if (rett->m_vinfo.transp.length == 0) { rett->__back__.fmt = CR_ARGBX555; rett->__vptr__ = &s_img15_vtbl; } else { rett->__back__.fmt = CR_ARGB1555; rett->__vptr__ = &s_img17_vtbl; } } else if (rett->m_vinfo.red.length == 4 && rett->m_vinfo.green.length == 4 && rett->m_vinfo.blue.length == 4 && rett->m_vinfo.red.offset == 8 && rett->m_vinfo.green.offset == 4 && rett->m_vinfo.blue.offset == 0) { rett->__back__.fmt = CR_ARGB4444; rett->__vptr__ = &s_img12_vtbl; } else { goto _failure; } rett->__back__.bpc = 2; } else if (rett->m_vinfo.bits_per_pixel == 32) { rett->__back__.bpc = 4; rett->__back__.fmt = CR_ARGB8888; rett->__vptr__ = &s_img32_vtbl; } else if (rett->m_vinfo.bits_per_pixel == 24) { rett->__back__.bpc = 3; rett->__back__.fmt = CR_ARGB888; rett->__vptr__ = &s_img24_vtbl; } else { goto _failure; } rett->__back__.data = (byte_t*)mem_malloc(rett->__back__.size + 16); if (rett->__back__.data == NULL) goto _failure; mem_zero(rett->__back__.data, rett->__back__.size); /* 映射前台缓冲 */ rett->m_size = (uint_t)rett->__back__.size; rett->m_main = mmap(NULL, rett->m_size, PROT_READ | PROT_WRITE, MAP_SHARED, rett->m_file, 0); if (rett->m_main == MAP_FAILED) { mem_free(rett->__back__.data); goto _failure; } mem_zero(rett->m_main, rett->m_size); return (rett); _failure: close(rett->m_file); return (NULL); }
/* ======================================= 生成 DX8 图形绘制接口 ======================================= */ CR_API iGFX2_DX8M* create_dx8_canvas ( __CR_IN__ const sDX8_HDLE* hdle, __CR_IN__ uint_t scn_cw, __CR_IN__ uint_t scn_ch, __CR_IN__ bool_t full ) { RECT rect; HRESULT retc; sD3D8_TEXR* fill; iGFX2_DX8M* rett; /* 使用伪全屏 */ if (full) { scn_cw = GetSystemMetrics(SM_CXSCREEN); scn_ch = GetSystemMetrics(SM_CYSCREEN); if (!SetWindowPos(hdle->hwnd, HWND_TOP, 0, 0, scn_cw, scn_ch, SWP_SHOWWINDOW)) return (NULL); } else if (scn_cw == 0 || scn_ch == 0) { /* 非法宽高, 获取窗口大小 */ if (!GetClientRect(hdle->hwnd, &rect)) return (NULL); scn_cw = rect.right; scn_ch = rect.bottom; } /* 生成对象 */ rett = struct_new(iGFX2_DX8M); if (rett == NULL) return (NULL); struct_zero(&rett->__back__, sIMAGE); /* 创建 D3D8 设备 */ if (hdle->main == NULL) { rett->m_main = hdle->call->create_main(hdle->hwnd, FALSE, scn_cw, scn_ch, D3DFMT_UNKNOWN, D3DFMT_UNKNOWN, FALSE, D3DMULTISAMPLE_NONE); if (rett->m_main == NULL) goto _failure1; } else { rett->m_main = hdle->main; } /* 创建填充用的纹理 */ fill = hdle->call->create_tex2(rett->m_main, 1, 1, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, 0, 1); if (fill == NULL) goto _failure2; rett->m_fill = (iGFX2*)create_dx8_bitmap(rett, fill, FALSE); if (rett->m_fill == NULL) { hdle->call->release_texr(fill); goto _failure2; } if (!CR_VCALL(rett->m_fill)->clear(rett->m_fill, 0xFFFFFFFFUL, 0)) goto _failure3; /* 生成精灵绘制对象 */ retc = D3DXCreateSprite(rett->m_main->dev, &rett->m_sprt); if (FAILED(retc)) goto _failure3; /* 返回生成的对象 */ rett->__vptr__ = &s_canvas_vtbl; struct_cpy(&rett->m_hdle, hdle, sDX8_HDLE); rect_set_wh(&rett->__back__.clip_win, 0, 0, scn_cw, scn_ch); struct_cpy(&rett->__back__.position, &rett->__back__.clip_win, sRECT); return (rett); _failure3: CR_VCALL(rett->m_fill)->release(rett->m_fill); _failure2: if (hdle->main == NULL) hdle->call->release_main(rett->m_main); _failure1: mem_free(rett); return (NULL); }
/* ======================================= KrKr XP3 文件读取 ======================================= */ CR_API sFMT_PRT* load_krkr_xp3 ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { int16u idx; int16u len; int32u attr; int64u tots; int64u tsz1; int64u tsz2; int64u pksz; int64u unsz; leng_t back; sARRAY list; byte_t* info; byte_t* pntr; wide_t* name; sXP3_HDR head; iPAK_XP3* port; sFMT_PRT* rett; sPAK_XP3_FILE temp; /* 必须使用自己私有的读取接口 */ datin = create_file_inX(param); if (datin == NULL) return (NULL); array_initT(&list, sPAK_XP3_FILE); list.free = xp3_free; /* 读取文件头信息 */ if (!(CR_VCALL(datin)->geType(datin, &head, sXP3_HDR))) goto _failure1; if (mem_cmp(head.tag, "XP3\r\n \n\x1A\x8B\x67\x01", 11) != 0) goto _failure1; head.idx_pos = QWORD_LE(head.idx_pos); /* 读取文件索引表 */ if (!CR_VCALL(datin)->seek64(datin, head.idx_pos, SEEK_SET)) goto _failure1; if (!CR_VCALL(datin)->getb_no(datin, head.tag)) goto _failure1; if (head.tag[0]) { /* ZLib 压缩的索引表 */ if (!CR_VCALL(datin)->getq_le(datin, &pksz)) goto _failure1; if (!CR_VCALL(datin)->getq_le(datin, &unsz)) goto _failure1; pntr = (byte_t*)mem_malloc64(pksz); if (pntr == NULL) goto _failure1; back = CR_VCALL(datin)->read(datin, pntr, (leng_t)pksz); if (back != (leng_t)pksz) { mem_free(pntr); goto _failure1; } info = (byte_t*)mem_malloc64(unsz); if (info == NULL) { mem_free(pntr); goto _failure1; } back = uncompr_zlib(info, (leng_t)unsz, pntr, (leng_t)pksz); mem_free(pntr); if (back != (leng_t)unsz) goto _failure2; } else { /* 直接读起索引表 */ if (!CR_VCALL(datin)->getq_le(datin, &unsz)) goto _failure1; info = (byte_t*)mem_malloc64(unsz); if (info == NULL) goto _failure1; back = CR_VCALL(datin)->read(datin, info, (leng_t)unsz); if (back != (leng_t)unsz) goto _failure2; } /* 设置加密类型 (如果有的话) */ if (param->aprm != NULL && *(byte_t*)param->aprm != 0x00) attr = PAK_FILE_ENC; else attr = 0; /* 加载文件信息表 */ for (pntr = info, pksz = 0; pksz < unsz;) { /* "File" 数据块 */ if (mem_cmp(pntr, "File", 4) != 0) break; mem_cpy(&tots, pntr + 4, sizeof(int64u)); tots = QWORD_LE(tots); pntr += 12; pksz += 12; if (tots <= 12 + 22 + 12 + 28 || tots > unsz - pksz) goto _failure2; /* "info" 文件总信息 */ if (mem_cmp(pntr, "info", 4) != 0) goto _failure2; mem_cpy(&tsz1, pntr + 4, sizeof(int64u)); tsz1 = QWORD_LE(tsz1); pntr += 12; pksz += 12; if (tsz1 <= 22 || tsz1 > tots - 12 - 12 - 28) goto _failure2; /* 填充一些文件信息结构成员 */ struct_zero(&temp, sPAK_XP3_FILE); mem_cpy(&temp.protect, pntr + 0, sizeof(int32u)); mem_cpy(&temp.base.size, pntr + 4, sizeof(int64u)); mem_cpy(&temp.base.pack, pntr + 12, sizeof(int64u)); temp.base.skip = sizeof(sPAK_XP3_FILE); temp.base.attr = attr; temp.protect = DWORD_LE(temp.protect); temp.base.size = QWORD_LE(temp.base.size); temp.base.pack = QWORD_LE(temp.base.pack); /* 读取文件名 UTF-16 无\0结尾 */ mem_cpy(&len, pntr + 20, sizeof(int16u)); len = WORD_LE(len); if ((int64u)len > tsz1 - 22) goto _failure2; name = str_allocW(len + 1); if (name == NULL) goto _failure2; for (idx = 0; idx < len; idx++) { mem_cpy(&name[idx], pntr + 22 + ((leng_t)idx) * 2, 2); name[idx] = WORD_LE(name[idx]); } name[idx] = 0x0000; temp.base.name = utf16_to_utf8(name); mem_free(name); if (temp.base.name == NULL) goto _failure2; pntr += (leng_t)tsz1; pksz += (leng_t)tsz1; /* "segm" 文件分段信息 */ if (mem_cmp(pntr, "segm", 4) != 0) goto _failure3; mem_cpy(&tsz2, pntr + 4, sizeof(int64u)); tsz2 = QWORD_LE(tsz2); pntr += 12; pksz += 12; if (tsz2 < 28 || tsz2 % 28 != 0 || tsz2 > tots - 12 - tsz1 - 12) goto _failure3; /* 读取所有分段信息 */ temp.segm_lst = mem_talloc64(tsz2 / 28, sPAK_XP3_SEGM); if (temp.segm_lst == NULL) goto _failure3; temp.segm_cnt = (leng_t)(tsz2 / 28); mem_cpy(temp.segm_lst, pntr, (leng_t)tsz2); for (back = 0; back < temp.segm_cnt; back++) { temp.segm_lst[back].zlib = DWORD_LE(temp.segm_lst[back].zlib); temp.segm_lst[back].offset = QWORD_LE(temp.segm_lst[back].offset); temp.segm_lst[back].unsize = QWORD_LE(temp.segm_lst[back].unsize); temp.segm_lst[back].pksize = QWORD_LE(temp.segm_lst[back].pksize); if (temp.segm_lst[back].unsize > temp.base.size) goto _failure4; if (temp.segm_lst[back].pksize > temp.base.pack) goto _failure4; } pntr += (leng_t)tsz2; pksz += (leng_t)tsz2; /* 其他非重要数据段 */ if (tots > 12 + tsz1 + 12 + tsz2) { tots -= 12 + tsz1 + 12 + tsz2; /* "adlr" 附加数据 */ if (mem_cmp(pntr, "adlr", 4) == 0) { if (tots < 16) goto _failure4; mem_cpy(&temp.adlr_key, pntr + 4, sizeof(int32u)); temp.adlr_key = DWORD_LE(temp.adlr_key); } pntr += (leng_t)tots; pksz += (leng_t)tots; } /* 用第一段设置剩下的成员 */ temp.base.offs = temp.segm_lst[0].offset; if (temp.segm_lst[0].zlib) { if (attr == 0) temp.base.memo = "ZLib"; else temp.base.memo = "ZLib + Encrypt"; temp.base.attr |= PAK_FILE_CMP; } else { if (attr == 0) temp.base.memo = "Store"; else temp.base.memo = "Encrypt"; } /* 文件信息压入列表 */ if (array_push_growT(&list, sPAK_XP3_FILE, &temp) == NULL) goto _failure4; } mem_free(info); /* 固定一下列表大小 */ if (!array_no_growT(&list, sPAK_XP3_FILE)) goto _failure1; /* 生成读包接口对象 */ port = struct_new(iPAK_XP3); if (port == NULL) goto _failure1; port->m_file = datin; port->m_cnt = array_get_sizeT(&list, sPAK_XP3_FILE); port->pack.__filelst__ = array_get_dataT(&list, sPAK_FILE); port->pack.__vptr__ = &s_pack_vtbl; if (!pack_init_list((iPACKAGE*)port, TRUE)) { mem_free(port); goto _failure1; } /* 设置解密回调 (传入名称字符串) */ if (attr != 0) { decode_setup(port, (ansi_t*)param->aprm); } else { port->decode_file = NULL; port->decode_block = NULL; } /* 返回读取的文件数据 */ rett = struct_new(sFMT_PRT); if (rett == NULL) { iPAK_XP3_release((iPACKAGE*)port); return (NULL); } rett->type = CR_FMTZ_PRT; rett->port = (iPORT*)port; rett->more = "iPACKAGE"; rett->infor = "KiriKiri2 XP3 Archive (XP3)"; return (rett); _failure4: mem_free(temp.segm_lst); _failure3: mem_free(temp.base.name); _failure2: mem_free(info); _failure1: array_freeT(&list, sPAK_XP3_FILE); CR_VCALL(datin)->release(datin); return (NULL); }
/* ======================================= RAR 文件读取 ======================================= */ CR_API sFMT_PRT* load_rar ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { HANDLE rar; sARRAY list; int32u attr; sint_t retc; leng_t fpos; iPAK_RAR* port; sFMT_PRT* rett; sPAK_RAR_FILE temp; RARHeaderDataEx info; RAROpenArchiveDataEx open; /* 只支持磁盘文件 */ if (param->type != CR_LDR_ANSI && param->type != CR_LDR_WIDE) return (NULL); /* 列表模式打开 RAR 文件 */ struct_zero(&open, RAROpenArchiveDataEx); if (param->type == CR_LDR_ANSI) open.ArcName = (ansi_t*)param->name.ansi; else open.ArcNameW = (wide_t*)param->name.wide; open.OpenMode = RAR_OM_LIST; rar = RAROpenArchiveEx(&open); if (rar == NULL) return (NULL); if (param->aprm != NULL && *(byte_t*)param->aprm != 0x00) { RARSetPassword(rar, (ansi_t*)param->aprm); attr = PAK_FILE_ENC; } else { attr = 0; } /* 开始逐个文件读取信息并定位 */ array_initT(&list, sPAK_RAR_FILE); list.free = rar_free; struct_zero(&info, RARHeaderDataEx); for (fpos = 0; ; fpos++) { /* 读取一个文件记录头 */ retc = RARReadHeaderEx(rar, &info); if (retc == ERAR_END_ARCHIVE) break; if (retc != ERAR_SUCCESS) goto _failure1; /* 目录文件不加入列表 */ if (info.Flags & RHDF_DIRECTORY) { retc = RARProcessFile(rar, RAR_SKIP, NULL, NULL); if (retc != ERAR_SUCCESS) goto _failure1; continue; } /* 文件名统一使用 UTF-8 编码 */ struct_zero(&temp, sPAK_RAR_FILE); temp.base.name = local_to_utf8(param->page, info.FileName); if (temp.base.name == NULL) goto _failure1; /* 设置公用文件属性 (偏移没有实际用处) */ temp.base.skip = sizeof(sPAK_RAR_FILE); temp.base.attr = attr; temp.base.offs = 0; temp.base.pack = mk_size(info.PackSizeHigh, info.PackSize); temp.base.size = mk_size(info.UnpSizeHigh, info.UnpSize); if (info.Method != 0x30) temp.base.attr |= PAK_FILE_CMP; if (info.Flags & RHDF_ENCRYPTED) temp.base.attr |= PAK_FILE_ENC; else temp.base.attr &= ~PAK_FILE_ENC; switch (info.Method) { case 0x30: temp.base.memo = "Storing"; break; case 0x31: temp.base.memo = "Fastest compression"; break; case 0x32: temp.base.memo = "Fast compression"; break; case 0x33: temp.base.memo = "Normal compression"; break; case 0x34: temp.base.memo = "Good compression"; break; case 0x35: temp.base.memo = "Best compression"; break; default: temp.base.memo = "Unknown compression"; break; } /* 设置私有文件属性 */ temp.id = fpos; temp.crc32 = (int32u)(info.FileCRC); temp.fattr = (int32u)(info.FileAttr); temp.ftime = (int16u)(info.FileTime & 0xFFFF); temp.fdate = (int16u)(info.FileTime >> 16); temp.htype = (int32u)(info.HashType); mem_cpy(temp.hash, info.Hash, sizeof(temp.hash)); /* 文件信息压入列表 */ if (array_push_growT(&list, sPAK_RAR_FILE, &temp) == NULL) { mem_free(temp.base.name); goto _failure1; } /* 跳过当前已读文件 */ retc = RARProcessFile(rar, RAR_SKIP, NULL, NULL); if (retc != ERAR_SUCCESS && retc != ERAR_BAD_DATA) goto _failure1; } /* 固定一下列表大小 */ if (!array_no_growT(&list, sPAK_RAR_FILE)) goto _failure1; /* 生成读包接口对象 */ port = struct_new(iPAK_RAR); if (port == NULL) goto _failure1; /* 保存需要用到的参数 */ port->m_temp = NULL; if (attr == 0) { port->m_pass = NULL; } else { port->m_pass = str_dupA((ansi_t*)param->aprm); if (port->m_pass == NULL) goto _failure2; } if (param->type == CR_LDR_ANSI) { port->m_wide = NULL; port->m_ansi = str_dupA(param->name.ansi); if (port->m_ansi == NULL) goto _failure3; } else { port->m_ansi = NULL; port->m_wide = str_dupW(param->name.wide); if (port->m_wide == NULL) goto _failure3; } port->m_rar = NULL; port->m_cur = (leng_t)-1; port->m_cnt = array_get_sizeT(&list, sPAK_RAR_FILE); port->pack.__filelst__ = array_get_dataT(&list, sPAK_FILE); port->pack.__vptr__ = &s_pack_vtbl; if (!pack_init_list((iPACKAGE*)port, TRUE)) goto _failure4; RARCloseArchive(rar); /* 返回读取的文件数据 */ rett = struct_new(sFMT_PRT); if (rett == NULL) { iPAK_RAR_release((iPACKAGE*)port); return (NULL); } CR_NOUSE(datin); rett->type = CR_FMTZ_PRT; rett->port = (iPORT*)port; rett->more = "iPACKAGE"; rett->infor = "Roshal ARchive (RAR)"; return (rett); _failure4: TRY_FREE(port->m_ansi); TRY_FREE(port->m_wide); _failure3: TRY_FREE(port->m_pass); _failure2: mem_free(port); _failure1: array_freeT(&list, sPAK_RAR_FILE); RARCloseArchive(rar); return (NULL); }
/* --------------------------------------- 读取文件数据 --------------------------------------- */ static bool_t iPAK_RAR_getFileData ( __CR_IN__ iPACKAGE* that, __CR_OT__ sBUFFER* buff, __CR_IN__ int64u index, __CR_IN__ bool_t hash ) { sint_t rett; int64u size; void_t* data; iPAK_RAR* real; sPAK_RAR_FILE* item; RARHeaderDataEx info; RAROpenArchiveDataEx open; /* 定位文件索引 */ CR_NOUSE(hash); real = (iPAK_RAR*)that; if (index >= real->m_cnt) return (FALSE); item = (sPAK_RAR_FILE*)real->pack.__filelst__; item += (leng_t)index; /* 获取文件数据 (0大小文件分配1个字节) */ size = item->base.size; if (size == 0) { data = mem_malloc(1); if (data == NULL) return (FALSE); size = 1; *(byte_t*)data = 0x00; } else { real->m_temp = data = mem_malloc64(size); if (data == NULL) return (FALSE); /* RAR 只能顺序读取文件 */ if (real->m_rar == NULL || item->id < real->m_cur) { /* 需要重新打开封包 */ if (real->m_rar != NULL) { RARCloseArchive(real->m_rar); real->m_rar = NULL; } struct_zero(&open, RAROpenArchiveDataEx); if (real->m_ansi != NULL) open.ArcName = real->m_ansi; else open.ArcNameW = real->m_wide; open.OpenMode = RAR_OM_EXTRACT; open.Callback = rar_mem_copy; open.UserData = (LPARAM)(&real->m_temp); real->m_rar = RAROpenArchiveEx(&open); if (real->m_rar == NULL) goto _failure1; if (real->m_pass != NULL) RARSetPassword(real->m_rar, real->m_pass); real->m_cur = 0; } /* 定位到指定文件 */ struct_zero(&info, RARHeaderDataEx); while (real->m_cur != item->id) { rett = RARReadHeaderEx(real->m_rar, &info); if (rett != ERAR_SUCCESS) goto _failure2; rett = RARProcessFile(real->m_rar, RAR_SKIP, NULL, NULL); if (rett != ERAR_SUCCESS && rett != ERAR_BAD_DATA) goto _failure2; real->m_cur += 1; } /* 测试目标文件就不会有磁盘操作了 */ rett = RARReadHeaderEx(real->m_rar, &info); if (rett != ERAR_SUCCESS) goto _failure2; rett = RARProcessFile(real->m_rar, RAR_TEST, NULL, NULL); if (rett != ERAR_SUCCESS) goto _failure2; real->m_cur += 1; } /* 返回文件数据 */ return (buffer_init(buff, data, (leng_t)size, TRUE)); _failure2: RARCloseArchive(real->m_rar); real->m_rar = NULL; _failure1: real->m_cur = (leng_t)-1; mem_free(data); return (FALSE); }
/* ======================================= FMODEx 文件读取 ======================================= */ CR_API sFMT_PRT* load_fmodex ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { uint_t size; void_t* data; ansi_t* path; sFMT_PRT* rett; FMOD_MODE mode; iXMM_FMOD* port; FMOD_SOUND* sound; FMOD_RESULT result; FMOD_CHANNEL* channel; FMOD_CREATESOUNDEXINFO ex_info; /* 必须先初始化 */ if (s_fmodex == NULL) return (NULL); mode = FMOD_LOOP_OFF | FMOD_2D | FMOD_HARDWARE | FMOD_ACCURATETIME; /* 不支持文件区段功能 */ switch (param->type) { case CR_LDR_ANSI: data = NULL; result = FMOD_System_CreateStream(s_fmodex, param->name.ansi, mode, NULL, &sound); break; case CR_LDR_WIDE: data = NULL; path = utf16_to_local(CR_LOCAL, param->name.wide); if (path == NULL) return (NULL); result = FMOD_System_CreateStream(s_fmodex, path, mode, NULL, &sound); mem_free(path); break; case CR_LDR_BUFF: if (cut_size(&size, param->buff.size)) return (NULL); data = mem_dup(param->buff.data, param->buff.size); if (data == NULL) return (NULL); path = (ansi_t*)data; mode |= FMOD_OPENMEMORY; mem_zero(&ex_info, sizeof(ex_info)); ex_info.cbsize = sizeof(ex_info); ex_info.length = size; result = FMOD_System_CreateStream(s_fmodex, path, mode, &ex_info, &sound); break; default: return (NULL); } /* 无法支持的格式 */ if (result != FMOD_OK) goto _failure1; /* 生成播放通道对象 */ result = FMOD_System_PlaySound(s_fmodex, FMOD_CHANNEL_FREE, sound, TRUE, &channel); if (result != FMOD_OK) goto _failure2; /* 生成媒体播放接口对象 */ port = struct_new(iXMM_FMOD); if (port == NULL) goto _failure3; struct_zero(port, iXMM_FMOD); port->m_dat = data; port->m_snd = sound; port->m_chn = channel; if (!fmodex_info(port)) { iXMM_FMOD_release((iXMMEDIA*)port); return (NULL); } port->xmms.__volume__ = 100; port->xmms.__vptr__ = &s_xmms_vtbl; /* 返回读取的文件数据 */ rett = struct_new(sFMT_PRT); if (rett == NULL) { iXMM_FMOD_release((iXMMEDIA*)port); return (NULL); } CR_NOUSE(datin); rett->type = CR_FMTZ_PRT; rett->port = (iPORT*)port; rett->more = "iXMMEDIA"; rett->infor = port->m_inf; return (rett); _failure3: FMOD_Channel_Stop(channel); _failure2: FMOD_Sound_Release(sound); _failure1: TRY_FREE(data); return (NULL); }