/* ======================================= SZ20 文件读取 ======================================= */ CR_API sFMT_DAT* load_ms_sz20 ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { leng_t pksz; leng_t unsz; void_t* data; void_t* temp; sFMT_DAT* rett; sSZ20_HDR head; /* 这个参数可能为空 */ if (datin == NULL) return (NULL); /* 读取 & 检查头部 */ if (!(CR_VCALL(datin)->geType(datin, &head, sSZ20_HDR))) return (NULL); if (mem_cmp(head.tag, "SZ\x20\x88\xF0\x27\x33\xD1", 8) != 0) return (NULL); /* 读取所有后续数据 */ temp = CR_VCALL(datin)->get(datin, &pksz, FALSE); if (temp == NULL) return (NULL); /* 分配目标数据缓冲 */ head.unsize = DWORD_LE(head.unsize); data = mem_malloc32(head.unsize); if (data == NULL) { mem_free(temp); return (NULL); } unsz = (leng_t)(head.unsize); pksz = uncompr_lzss(data, unsz, temp, pksz, 0x20); mem_free(temp); if (pksz != unsz) goto _failure; /* 返回读取的文件数据 */ rett = struct_new(sFMT_DAT); if (rett == NULL) goto _failure; CR_NOUSE(param); rett->type = CR_FMTZ_DEC; rett->unsz = unsz; rett->pksz = dati_get_size(datin); rett->data = data; rett->infor = "Microsoft Compressed (SZ20) file"; return (rett); _failure: mem_free(data); return (NULL); }
/* ======================================= TGL IEL1 文件读取 ======================================= */ CR_API sFMT_DAT* load_tgl_iel1 ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { leng_t pksz; leng_t unsz; void_t* data; void_t* temp; sFMT_DAT* rett; sIEL1_HDR head; /* 这个参数可能为空 */ if (datin == NULL) return (NULL); /* 读取 & 检查头部 */ if (!(CR_VCALL(datin)->geType(datin, &head, sIEL1_HDR))) return (NULL); if (head.magic != mk_tag4("IEL1")) return (NULL); /* 读取所有后续数据 */ temp = CR_VCALL(datin)->get(datin, &pksz, FALSE); if (temp == NULL) return (NULL); /* 分配目标数据缓冲 */ head.unsize = DWORD_LE(head.unsize); data = mem_malloc32(head.unsize); if (data == NULL) { mem_free(temp); return (NULL); } unsz = (leng_t)(head.unsize); pksz = uncompr_lzss(data, unsz, temp, pksz, 0); mem_free(temp); if (pksz != unsz) goto _failure; /* 返回读取的文件数据 */ rett = struct_new(sFMT_DAT); if (rett == NULL) goto _failure; CR_NOUSE(param); rett->type = CR_FMTZ_DEC; rett->unsz = unsz; rett->pksz = dati_get_size(datin); rett->data = data; rett->infor = "TGL LZSS Compressed file (IEL1)"; return (rett); _failure: mem_free(data); return (NULL); }
/* --------------------------------------- 创建文字绘制对象 (UCDOS 点阵) --------------------------------------- */ static bool_t qst_crh_ucfont ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { iDATIN* asc; iDATIN* hzk; iDATIN* chr; ansi_t name[MAX_PATHA]; uint_t size, xspc, yspc; CR_NOUSE(parm); /* 参数解析 <Size> <XSpace> <YSpace> [Suffix] */ if (argc < 4) return (FALSE); /* 加载点阵字库文件 */ size = str2intxA(argv[1]); if (argc == 4) { sprintf(name, QST_PATH_SOURCE "ucfont\\HZK%u", size); } else { sprintf(name, QST_PATH_SOURCE "ucfont\\HZK%u%c", size, (argv[4])[0]); } hzk = create_disk_inA(name); if (hzk == NULL) return (FALSE); sprintf(name, QST_PATH_SOURCE "ucfont\\ASC%u", size); asc = create_disk_inA(name); sprintf(name, QST_PATH_SOURCE "ucfont\\HZK%uT", size); chr = create_disk_inA(name); /* 创建 UCDOS 点阵汉字绘制对象 */ xspc = str2intxA(argv[2]); yspc = str2intxA(argv[3]); if (s_font != NULL) CR_VCALL(s_font)->release(s_font); s_font = create_ucdos_font(asc, hzk, chr, size, xspc, yspc); if (s_font == NULL) { CR_VCALL(hzk)->release(hzk); if (asc != NULL) CR_VCALL(asc)->release(asc); if (chr != NULL) CR_VCALL(chr)->release(chr); return (FALSE); } return (TRUE); }
/* --------------------------------------- 读取文件数据 --------------------------------------- */ static bool_t iPAK_IPAC_getFileData ( __CR_IN__ iPACKAGE* that, __CR_OT__ sBUFFER* buff, __CR_IN__ int64u index, __CR_IN__ bool_t hash ) { int64u size; void_t* data; iDATIN* file; iPAK_IPAC* real; sPAK_FILE* item; /* 定位文件索引 */ CR_NOUSE(hash); real = (iPAK_IPAC*)that; if (index >= real->m_cnt) return (FALSE); item = real->pack.__filelst__; item += (uint_t)index; /* 获取文件数据 (0大小文件分配1个字节) */ size = item->size; if (size == 0) { data = mem_malloc(1); if (data == NULL) return (FALSE); size = 1; *(byte_t*)data = 0x00; } else { data = mem_malloc64(size); if (data == NULL) return (FALSE); file = real->m_file; /* 定位到文件并读起数据 */ if (!CR_VCALL(file)->seek64(file, item->offs, SEEK_SET)) goto _failure; if (CR_VCALL(file)->read(file, data, (leng_t)size) != (leng_t)size) goto _failure; } /* 返回文件数据 */ return (buffer_init(buff, data, (leng_t)size, TRUE)); _failure: mem_free(data); return (FALSE); }
/* --------------------------------------- 是否为 GDI 文字输出对象 --------------------------------------- */ inline bool_t is_gdi_text_out (void_t) { if (CR_VCALL(s_font)->getMore(s_font, "iFONT::GDI") != NULL) return (TRUE); return (FALSE); }
/* --------------------------------------- 关闭通讯接口 --------------------------------------- */ static bool_t qst_com_close ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { sQstComm* ctx; CR_NOUSE(argc); CR_NOUSE(argv); ctx = (sQstComm*)parm; if (ctx->comm.thrd == NULL) return (FALSE); ctx->comm.quit = TRUE; thread_wait(ctx->comm.thrd); thread_del(ctx->comm.thrd); ctx->comm.thrd = NULL; ctx->comm.quit = FALSE; SAFE_FREE(ctx->comm.title); qst_update_title(ctx); CR_VCALL(ctx->bufs)->reput(ctx->bufs, 0); ctx->size = 0; return (TRUE); }
/* ======================================= RS232 接收线程 ======================================= */ CR_API uint_t STDCALL qst_rs232_main ( __CR_IN__ void_t* parm ) { sQstComm* ctx = (sQstComm*)parm; /* 工作循环 */ while (!ctx->comm.quit) { uint_t back; ansi_t cha, *data; /* 一个个字节读 */ back = sio_read(ctx->comm.obj.port, &cha, 1); if (back == 1) { if (CR_VCALL(ctx->bufs)->putb_no(ctx->bufs, cha)) ctx->size += 1; continue; } if (back != 0) { thread_sleep(20); continue; } /* 文本模式处理 */ if (ctx->size == 0) continue; data = (ansi_t*)(CR_VCALL(ctx->bufs)->flush(ctx->bufs)); if (ctx->comm.text) ctx->size = qst_txt_mode(data, ctx->size); /* 渲染读到的内容 */ _ENTER_COM_SINGLE_ ctx->comm.render(parm, data, ctx->size); _LEAVE_COM_SINGLE_ /* 缓存指针复位 */ CR_VCALL(ctx->bufs)->reput(ctx->bufs, 0); ctx->size = 0; } /* 退出时关闭串口 */ sio_close(ctx->comm.obj.port); return (QST_OKAY); }
/* --------------------------------------- 创建文字绘制对象 (自定义点阵) --------------------------------------- */ static bool_t qst_crh_btfont ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { iDATIN* asc; iDATIN* hzk; ansi_t name[MAX_PATHA]; uint_t size, xspc, yspc; CR_NOUSE(parm); /* 参数解析 <Size> <XSpace> <YSpace> <Type> */ if (argc < 5) return (FALSE); /* 加载点阵字库文件 */ size = str2intxA(argv[1]); sprintf(name, QST_PATH_SOURCE "btfont\\%s_%u.full", argv[4], size); hzk = create_disk_inA(name); if (hzk == NULL) return (FALSE); sprintf(name, QST_PATH_SOURCE "btfont\\%s_%u.half", argv[4], size); asc = create_disk_inA(name); if (asc == NULL) { CR_VCALL(hzk)->release(hzk); return (FALSE); } /* 创建自定义点阵文字绘制对象 */ xspc = str2intxA(argv[2]); yspc = str2intxA(argv[3]); if (s_font != NULL) CR_VCALL(s_font)->release(s_font); s_font = create_bit_font(asc, hzk, size, xspc, yspc, argv[4]); if (s_font == NULL) { CR_VCALL(hzk)->release(hzk); CR_VCALL(asc)->release(asc); return (FALSE); } return (TRUE); }
/* --------------------------------------- 创建文字绘制对象 (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); }
/* --------------------------------------- 释放图形绘制接口 --------------------------------------- */ static void_t iGFX2_DX8M_release ( __CR_IN__ iGFX2* that ) { iGFX2_DX8M* real; real = (iGFX2_DX8M*)that; real->m_sprt->Release(); CR_VCALL(real->m_fill)->release(real->m_fill); if (real->m_hdle.main == NULL) real->m_hdle.call->release_main(real->m_main); mem_free(that); }
/* --------------------------------------- 释放接口 --------------------------------------- */ static void_t iPAK_IPAC_release ( __CR_IN__ iPACKAGE* that ) { uint_t idx; iPAK_IPAC* real; sPAK_FILE* list; pack_free_list(that); real = (iPAK_IPAC*)that; list = real->pack.__filelst__; if (list != NULL) { for (idx = 0; idx < real->m_cnt; idx++) { mem_free(list[idx].find); mem_free(list[idx].name); } mem_free(list); } CR_VCALL(real->m_file)->release(real->m_file); mem_free(that); }
/* --------------------------------------- 释放接口 --------------------------------------- */ static void_t iPAK_XP3_release ( __CR_IN__ iPACKAGE* that ) { leng_t idx; iPAK_XP3* real; sPAK_XP3_FILE* list; pack_free_list(that); real = (iPAK_XP3*)that; list = (sPAK_XP3_FILE*)real->pack.__filelst__; if (list != NULL) { for (idx = 0; idx < real->m_cnt; idx++) { mem_free(list[idx].segm_lst); mem_free(list[idx].base.find); mem_free(list[idx].base.name); } mem_free(list); } CR_VCALL(real->m_file)->release(real->m_file); mem_free(that); }
/* --------------------------------------- 设置颜色 --------------------------------------- */ static bool_t qst_crh_color ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { CR_NOUSE(parm); /* 参数解析 <Red> <Green> <Blue> [Alpha] */ if (argc < 4) return (FALSE); s_color.c32.rrr = (byte_t)str2intxA(argv[1]); s_color.c32.ggg = (byte_t)str2intxA(argv[2]); s_color.c32.bbb = (byte_t)str2intxA(argv[3]); if (argc > 4) s_color.c32.lrp = (byte_t)str2intxA(argv[4]); else s_color.c32.lrp = 255; if (s_font == NULL) return (TRUE); return (CR_VCALL(s_font)->setColor(s_font, s_color.val)); }
/* ======================================= 生成 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); }
/* ======================================= LZSS-8 解压缩 ======================================= */ CR_API leng_t uncompr_lzss8 ( __CR_OT__ void_t* dst, __CR_IN__ leng_t dstlen, __CR_IN__ const void_t* src, __CR_IN__ leng_t srclen ) { leng_t o_ptr; byte_t* o_buf; sBITIN bitin; iDATIN* datin; uint_t cc, rr; uint_t ii, jj, kk; byte_t win[LZSS_N]; /* 建立位流输入对象 */ datin = create_buff_in(src, srclen, FALSE); if (datin == NULL) return (0); bitin_init(&bitin, datin, sizeof(byte_t)); o_ptr = 0; o_buf = (byte_t*)dst; rr = LZSS_N - LZSS_F; for (cc = 0; cc < LZSS_N; cc++) win[cc] = 0; while (o_ptr < dstlen) { if (!bitin_hi_push(&bitin, &cc, 1)) break; if (cc) { if (!bitin_hi_push(&bitin, &cc, 8)) goto _failure; if (o_ptr >= dstlen) goto _failure; win[rr++] = (byte_t)cc; o_buf[o_ptr++] = (byte_t)cc; rr &= (LZSS_N - 1); } else { if (!bitin_hi_push(&bitin, &ii, LZSS_EI)) goto _failure; if (!bitin_hi_push(&bitin, &jj, LZSS_EJ)) goto _failure; for (kk = 0; kk <= jj + 1; kk++) { if (o_ptr >= dstlen) goto _failure; cc = win[(ii + kk) & (LZSS_N - 1)]; win[rr++] = (byte_t)cc; o_buf[o_ptr++] = (byte_t)cc; rr &= (LZSS_N - 1); } } } CR_VCALL(datin)->release(datin); return (o_ptr); _failure: CR_VCALL(datin)->release(datin); return (0); }
/* ======================================= WinMain 程序入口 ======================================= */ int WINAPI WinMain ( __CR_IN__ HINSTANCE curt_app, __CR_IN__ HINSTANCE prev_app, __CR_IN__ LPSTR cmd_line, __CR_IN__ int cmd_show ) { CR_NOUSE(prev_app); CR_NOUSE(cmd_line); CR_NOUSE(cmd_show); /* 只允许一个例程 */ if (misc_is_running(EXE_XNAME)) return (QST_ERROR); /* 建立 CrHack 系统 */ if (!set_app_type(CR_APP_GUI)) return (QST_ERROR); mem_zero(&s_wrk_ctx, sizeof(s_wrk_ctx)); sint_t x1, y1; uint_t ww, hh; /* 生成一个可变大小的窗口 */ mtlock_init(&s_wrk_ctx.lock); qst_load_cfg(&s_wrk_ctx.cfgs); misc_desk_init(WIN_ICONF, &x1, &y1, &ww, &hh, QV2D_DEF_WIDTH, QV2D_DEF_HEIGHT); if (ww < QV2D_DEF_WIDTH) ww = QV2D_DEF_WIDTH; if (hh < QV2D_DEF_HEIGHT) hh = QV2D_DEF_HEIGHT; s_wrk_ctx.hwnd = (HWND)window_open(curt_app, (void_t*)WindowProc, x1, y1, ww, hh, WIN_TITLE, WIN_CLASS, (ansi_t*)101, CR_WSTYLE_NORMAL); if (s_wrk_ctx.hwnd == NULL) return (QST_ERROR); SetWindowLongPtr(s_wrk_ctx.hwnd, GWL_STYLE, GetWindowLongPtr(s_wrk_ctx.hwnd, GWL_STYLE) & (~WS_MAXIMIZEBOX)); iGFX2* draw; sIMAGE* imgs; /* 创建 GDI 绘制对象 (只支持32位色屏幕) */ draw = (iGFX2*)create_gdi_canvas(s_wrk_ctx.hwnd, 0, 0, FALSE); if (draw == NULL) { window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); return (QST_ERROR); } imgs = CR_VCALL(draw)->lock(draw); if (imgs == NULL || imgs->fmt != CR_ARGB8888) { window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); return (QST_ERROR); } CR_VCALL(draw)->unlock(draw); CR_VCALL(draw)->clear(draw, s_wrk_ctx.cfgs.bkcolor, 0); s_wrk_ctx.draw = draw; /* 初始化网络 */ if (!socket_init()) { window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); return (QST_ERROR); } s_wrk_ctx.netw = netw_cli_open(EXE_XNAME); if (s_wrk_ctx.netw == NULL) { window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); return (QST_ERROR); } /* 读取需要超时, 不然线程无法退出 */ socket_set_timeout(s_wrk_ctx.netw, -1, QST_TCP_TOUT); thrd_t thrd; /* 生成工作线程 */ s_wrk_ctx.send = TRUE; s_wrk_ctx.quit = FALSE; s_wrk_ctx.cur_busy = LoadCursor(NULL, IDC_WAIT); s_wrk_ctx.cur_free = LoadCursor(NULL, IDC_ARROW); s_wrk_ctx.res_loader = res_loader_get(); if (s_wrk_ctx.res_loader->init != NULL) s_wrk_ctx.res_loader->init(s_wrk_ctx.netw, NULL); qst_load_filter(&s_wrk_ctx); thrd = thread_new(0, qst_v2d_main, &s_wrk_ctx, FALSE); if (thrd == NULL) { window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); return (QST_ERROR); } /* 消息循环 */ while (!s_wrk_ctx.quit) { MSG msg; if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { s_wrk_ctx.quit = TRUE; break; } TranslateMessage(&msg); DispatchMessage(&msg); } else { qst_do_keyboard(&s_wrk_ctx); } } thread_wait(thrd); thread_del(thrd); window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); netw_cli_close(s_wrk_ctx.netw); return (QST_OKAY); }
/* ======================================= TGL IPAC 文件读取 ======================================= */ CR_API sFMT_PRT* load_tgl_ipac ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { int16u idx; int16u cnt; int32u offs; int32u size; sFMT_PRT* rett; sIPAC_HDR head; iPAK_IPAC* port; sPAK_FILE* list; ansi_t str[17]; /* 必须使用自己私有的读取接口 */ datin = create_file_inX(param); if (datin == NULL) return (NULL); /* 读取 & 检查头部 */ if (!(CR_VCALL(datin)->geType(datin, &head, sIPAC_HDR))) goto _failure1; if (head.magic != mk_tag4("IPAC")) goto _failure1; /* 分配子文件属性表 */ cnt = WORD_LE(head.count); if (cnt != 0) { list = mem_talloc(cnt, sPAK_FILE); if (list == NULL) goto _failure1; str[16] = CR_AC(NIL); mem_tzero(list, cnt, sPAK_FILE); } else { list = NULL; /* 支持空的包文件 */ } /* 加载文件信息表 */ for (idx = 0; idx < cnt; idx++) { /* 读取文件名不保证\0结尾 */ if (CR_VCALL(datin)->read(datin, str, 16) != 16) goto _failure2; /* 文件的包内偏移和大小 */ if (!CR_VCALL(datin)->getd_le(datin, &offs)) goto _failure2; if (!CR_VCALL(datin)->getd_le(datin, &size)) goto _failure2; /* 文件名统一使用 UTF-8 编码 */ list[idx].name = local_to_utf8(param->page, str); if (list[idx].name == NULL) goto _failure2; /* 设置公用文件属性 */ list[idx].skip = sizeof(sPAK_FILE); list[idx].attr = 0; list[idx].offs = offs; list[idx].pack = size; list[idx].size = size; list[idx].memo = "Store"; } /* 生成读包接口对象 */ port = struct_new(iPAK_IPAC); if (port == NULL) goto _failure2; port->m_cnt = cnt; port->m_file = datin; port->pack.__filelst__ = list; port->pack.__vptr__ = &s_pack_vtbl; if (!pack_init_list((iPACKAGE*)port, TRUE)) { mem_free(port); goto _failure2; } /* 返回读取的文件数据 */ rett = struct_new(sFMT_PRT); if (rett == NULL) { iPAK_IPAC_release((iPACKAGE*)port); return (NULL); } rett->type = CR_FMTZ_PRT; rett->port = (iPORT*)port; rett->more = "iPACKAGE"; rett->infor = "TGL IPAC Archive (IPAC)"; return (rett); _failure2: if (list != NULL) { for (cnt = 0; cnt < idx; cnt++) { TRY_FREE(list[cnt].find); mem_free(list[cnt].name); } mem_free(list); } _failure1: CR_VCALL(datin)->release(datin); 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); }
/* --------------------------------------- 读取文件数据 --------------------------------------- */ static bool_t iPAK_XP3_getFileData ( __CR_IN__ iPACKAGE* that, __CR_OT__ sBUFFER* buff, __CR_IN__ int64u index, __CR_IN__ bool_t hash ) { leng_t pntr; leng_t back; leng_t segm; int64u pack; int64u size; void_t* temp; void_t* data; iDATIN* file; iPAK_XP3* real; sPAK_XP3_FILE* item; /* 定位文件索引 */ CR_NOUSE(hash); real = (iPAK_XP3*)that; if (index >= real->m_cnt) return (FALSE); item = (sPAK_XP3_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 { pack = item->base.pack; temp = mem_malloc64(pack); if (temp == NULL) return (FALSE); data = mem_malloc64(size); if (data == NULL) goto _failure1; file = real->m_file; /* 定位到文件并读起数据 */ for (pntr = 0, segm = 0; segm < item->segm_cnt; segm++) { /* 逐块读取文件 */ if (!CR_VCALL(file)->seek64(file, item->segm_lst[segm].offset, SEEK_SET)) goto _failure2; /* 是否为 ZLib 压缩 */ if (item->segm_lst[segm].zlib) { back = CR_VCALL(file)->read(file, temp, (leng_t)item->segm_lst[segm].pksize); if (back != (leng_t)item->segm_lst[segm].pksize) goto _failure2; back = uncompr_zlib((byte_t*)data + pntr, (leng_t)size - pntr, temp, back); if (back != (leng_t)item->segm_lst[segm].unsize) goto _failure2; } else { back = CR_VCALL(file)->read(file, (byte_t*)data + pntr, (leng_t)item->segm_lst[segm].unsize); if (back != (leng_t)item->segm_lst[segm].unsize) goto _failure2; } /* 数据块解密 */ if (real->decode_block != NULL) real->decode_block((byte_t*)data + pntr, back, pntr, item); pntr += back; } /* 整个文件解密 */ if (real->decode_file != NULL) real->decode_file(data, (leng_t)size, item); mem_free(temp); } /* 返回文件数据 */ return (buffer_init(buff, data, (leng_t)size, TRUE)); _failure2: mem_free(data); _failure1: mem_free(temp); return (FALSE); }
/* ======================================= PNG 文件读取 ======================================= */ CR_API sFMT_PIC* load_cr_png ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { leng_t nbpl; leng_t sbpp; leng_t dptr; uint_t fcrh; uint_t index; uchar* image; uchar* sdata; uchar* ddata; leng_t dsize; int32u ssize; uint_t ww, hh; byte_t pal[768]; /* ----------- */ fsize_t fsze; sPNG_HDR head; sFMT_PIC* rett; sFMT_FRAME temp; /* 这个参数可能为空 */ if (datin == NULL) return (NULL); /* 读取 & 检查头部 */ if (!(CR_VCALL(datin)->geType(datin, &head, sPNG_HDR))) return (NULL); if (mem_cmp(&head, "\x89PNG\r\n\x1A\n\0\0\0\x0DIHDR", 16) != 0) return (NULL); if (head.info.compr != 0 || head.info.filter != 0 || head.info.interlace != 0) return (NULL); /* 对宽高的截断检查 */ if (cut_int32_u(&ww, DWORD_BE(head.info.w))) return (NULL); if (cut_int32_u(&hh, DWORD_BE(head.info.h))) return (NULL); /* 生成图片对象 */ mem_zero(temp.wh, sizeof(temp.wh)); switch (head.info.color) { case 0: /* 灰度图像 */ if (head.info.depth != 1 && head.info.depth != 2 && head.info.depth != 4 && head.info.depth != 8 && head.info.depth != 16) return (NULL); fcrh = CR_INDEX8; temp.fmt = CR_PIC_GREY; temp.bpp = head.info.depth; temp.clr = "I"; temp.wh[0] = head.info.depth; break; case 2: /* 真彩图像 */ if (head.info.depth != 8 && head.info.depth != 16) return (NULL); fcrh = CR_ARGB888; temp.fmt = CR_PIC_ARGB; temp.bpp = head.info.depth * 3; temp.clr = "BGR"; temp.wh[0] = head.info.depth; temp.wh[1] = head.info.depth; temp.wh[2] = head.info.depth; break; case 3: /* 索引图像 */ if (head.info.depth != 1 && head.info.depth != 2 && head.info.depth != 4 && head.info.depth != 8) return (NULL); fcrh = CR_INDEX8; temp.fmt = CR_PIC_PALS; temp.bpp = head.info.depth; temp.clr = "P"; temp.wh[0] = head.info.depth; break; case 4: /* α灰度图像 */ if (head.info.depth != 8 && head.info.depth != 16) return (NULL); fcrh = CR_ARGB8888; temp.fmt = CR_PIC_GREY; temp.bpp = head.info.depth * 2; temp.clr = "AI"; temp.wh[0] = head.info.depth; temp.wh[1] = head.info.depth; break; case 6: /* α真彩图像 */ if (head.info.depth != 8 && head.info.depth != 16) return (NULL); fcrh = CR_ARGB8888; temp.fmt = CR_PIC_ARGB; temp.bpp = head.info.depth * 4; temp.clr = "ABGR"; temp.wh[0] = head.info.depth; temp.wh[1] = head.info.depth; temp.wh[2] = head.info.depth; temp.wh[3] = head.info.depth; break; default: return (NULL); } sbpp = (temp.bpp - 1) / 8 + 1; temp.pic = image_new(0, 0, ww, hh, fcrh, FALSE, 4); if (temp.pic == NULL) return (NULL); /* 生成灰度调色板 */ if (temp.fmt == CR_PIC_GREY) pal_set_gray8(temp.pic->pal, 256); /* 分配 IDAT 的内存 */ fsze = dati_get_size(datin); if (fsze <= sizeof(sPNG_HDR) + sizeof(sIEND) * 2) goto _failure1; fsze -= sizeof(sPNG_HDR) + sizeof(sIEND) * 2; ddata = (byte_t*)mem_malloc64(fsze); if (ddata == NULL) goto _failure1; dsize = (leng_t)fsze; /* 读取数据块 */ dptr = 0; fcrh = 256; /* 这个保存调色板颜色数 */ do { /* 数据块大小 */ if (!(CR_VCALL(datin)->geType(datin, &head.info, sCHUNK))) goto _failure2; ssize = DWORD_BE(head.info.head.size); if (ssize > fsze) goto _failure2; if (head.info.head.name == mk_tag4("PLTE")) { /* 调色板, 安全检查 */ if (ssize > 768 || ssize % 3 != 0) goto _failure2; if (CR_VCALL(datin)->read(datin, pal, ssize) != ssize) goto _failure2; /* 转换到 4B 格式 */ fcrh = (uint_t)ssize / 3; pal_3b_to_4b_sw(temp.pic->pal, pal, fcrh); } else if (head.info.head.name == mk_tag4("IDAT")) { /* 检查缓冲溢出 */ if (dsize < ssize) goto _failure2; if (CR_VCALL(datin)->read(datin, ddata + dptr, ssize) != ssize) goto _failure2; dptr += ssize; dsize -= ssize; } else if (head.info.head.name == mk_tag4("tRNS")) { /* 透明数据 */ if (head.info.color == 0) { if (ssize != 2) goto _failure2; if (CR_VCALL(datin)->read(datin, pal, 2) != 2) goto _failure2; /* 调色板的这个颜色为透明色 */ if (head.info.depth != 16) temp.pic->pal[pal[1]] &= CDWORD_LE(0x00FFFFFFUL); } else if (head.info.color == 2) { if (ssize != 6) goto _failure2; if (CR_VCALL(datin)->read(datin, pal, 6) != 6) goto _failure2; /* 这个颜色为透明色, 这里只能展开来写 否则 C++Builder 2010 编译器编译时会崩溃 */ if (head.info.depth != 16) { temp.pic->keycolor = pal[1]; temp.pic->keycolor <<= 8; temp.pic->keycolor |= pal[3]; temp.pic->keycolor <<= 8; temp.pic->keycolor |= pal[5]; temp.pic->keycolor |= 0xFF000000UL; temp.pic->keycolor = DWORD_LE(temp.pic->keycolor); } } else if (head.info.color == 3) { if (ssize > fcrh) goto _failure2; if (CR_VCALL(datin)->read(datin, pal, ssize) != ssize) goto _failure2; /* 设置调色板的 Alpha 通道 */ for (fcrh = (uint_t)ssize, index = 0; index < fcrh; index++) ((uchar*)temp.pic->pal)[index * 4 + 3] = pal[index]; } else { goto _failure2; } } else { /* 跳过其他数据块 */ if (!CR_VCALL(datin)->seek(datin, ssize, SEEK_CUR)) goto _failure2; } /* 跳过 CRC-32 */ if (!CR_VCALL(datin)->seek(datin, 4, SEEK_CUR)) goto _failure2; } while (head.info.head.name != mk_tag4("IEND")); /* 无 IDAT 块 */ if (dptr == 0) goto _failure2; /* 分配带 filter 的图形内存 */ if (cut_mad(&dsize, ww, sbpp * hh, hh)) goto _failure2; sdata = (byte_t*)mem_malloc(dsize); if (sdata == NULL) goto _failure2; /* 解压图形数据 */ dptr = uncompr_zlib(sdata, dsize, ddata, dptr); mem_free(ddata); ddata = sdata; if (dptr <= hh) goto _failure2; image = temp.pic->data; /* 文件解码完毕, 解析图片的像素数据 */ if (temp.pic->fmt == CR_INDEX8) { switch (head.info.depth) { case 1: if (ww % 8 == 0) nbpl = ww / 8; else nbpl = ww / 8 + 1; if (!png_filter(ddata, nbpl, 1, hh, dptr)) goto _failure2; for (index = hh; index != 0; index--) { sdata = (uchar*)font1_h2l(image, sdata, ww); image += temp.pic->bpl; } break; case 2: if (ww % 4 == 0) nbpl = ww / 4; else nbpl = ww / 4 + 1; if (!png_filter(ddata, nbpl, 1, hh, dptr)) goto _failure2; for (index = hh; index != 0; index--) { sdata = (uchar*)font2_h2l(image, sdata, ww); image += temp.pic->bpl; } break; case 4: if (ww % 2 == 0) nbpl = ww / 2; else nbpl = ww / 2 + 1; if (!png_filter(ddata, nbpl, 1, hh, dptr)) goto _failure2; for (index = hh; index != 0; index--) { sdata = (uchar*)font4_h2l(image, sdata, ww); image += temp.pic->bpl; } break; case 8: nbpl = ww; if (!png_filter(ddata, nbpl, 1, hh, dptr)) goto _failure2; for (index = hh; index != 0; index--) { mem_cpy(image, sdata, nbpl); sdata += nbpl; image += temp.pic->bpl; } break; default: case 16: nbpl = ww; nbpl *= 2; if (!png_filter(ddata, nbpl, 2, hh, dptr)) goto _failure2; for (index = hh; index != 0; index--) { for (fcrh = 0; fcrh < ww; fcrh++, sdata += 2) image[fcrh] = sdata[0]; image += temp.pic->bpl; } break; } } else { nbpl = ww * sbpp; if (!png_filter(ddata, nbpl, sbpp, hh, dptr)) goto _failure2; nbpl = ww * temp.pic->bpc; switch (head.info.color) { case 2: if (head.info.depth == 8) { /* 直接逐行复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 3) { image[dsize + 0] = sdata[2]; image[dsize + 1] = sdata[1]; image[dsize + 2] = sdata[0]; sdata += 3; } image += temp.pic->bpl; } } else { /* 跳开一个像素复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 3) { image[dsize + 0] = sdata[4]; image[dsize + 1] = sdata[2]; image[dsize + 2] = sdata[0]; sdata += 6; } image += temp.pic->bpl; } } break; case 4: if (head.info.depth == 8) { /* 直接逐行复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 4) { image[dsize + 0] = sdata[0]; image[dsize + 1] = sdata[0]; image[dsize + 2] = sdata[0]; image[dsize + 3] = sdata[1]; sdata += 2; } image += temp.pic->bpl; } } else { /* 跳开一个像素复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 4) { image[dsize + 0] = sdata[0]; image[dsize + 1] = sdata[0]; image[dsize + 2] = sdata[0]; image[dsize + 3] = sdata[2]; sdata += 4; } image += temp.pic->bpl; } } break; default: case 6: if (head.info.depth == 8) { /* 直接逐行复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 4) { image[dsize + 0] = sdata[2]; image[dsize + 1] = sdata[1]; image[dsize + 2] = sdata[0]; image[dsize + 3] = sdata[3]; sdata += 4; } image += temp.pic->bpl; } } else { /* 跳开一个像素复制 */ for (index = hh; index != 0; index--) { for (dsize = 0; dsize < nbpl; dsize += 4) { image[dsize + 0] = sdata[4]; image[dsize + 1] = sdata[2]; image[dsize + 2] = sdata[0]; image[dsize + 3] = sdata[6]; sdata += 8; } image += temp.pic->bpl; } } break; } } mem_free(ddata); /* 返回读取的文件数据 */ rett = struct_new(sFMT_PIC); if (rett == NULL) goto _failure1; rett->frame = struct_dup(&temp, sFMT_FRAME); if (rett->frame == NULL) { mem_free(rett); goto _failure1; } CR_NOUSE(param); rett->type = CR_FMTZ_PIC; rett->count = 1; rett->infor = "Portable Network Graphics (PNG)"; return (rett); _failure2: mem_free(ddata); _failure1: image_del(temp.pic); return (NULL); }
/* ======================================= FALCOM AIA 文件读取 ======================================= */ CR_API sFMT_PRT* load_flc_aia ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { leng_t back; leng_t size; byte_t* pals; byte_t* dats; uint_t ww, hh; int32u idx, cnt; /* ----------- */ fdist_t offs; sAIA_HDR head; sAIA_IDX* attr; sFMT_PRT* rett; iPIC_AIA* port; /* 这个参数可能为空 */ if (datin == NULL) return (NULL); /* 读取 & 检查头部 */ if (!(CR_VCALL(datin)->geType(datin, &head, sAIA_HDR))) return (NULL); if (head.magic != mk_tag4("AIA")) return (NULL); offs = DWORD_LE(head.idx_num); offs *= sizeof(int32u) * 4; if (head.version == CWORD_LE(0x140)) { offs += 32; pals = (byte_t*)(&head.img_size); dats = (byte_t*)(&head.scale1); mem_cpy(pals, dats, 4); pals = (byte_t*)(&head.ww2); mem_cpy(dats, pals, 4); head.ww2 = head.hh2 = 0; head.scale2 = 0.0f; } else if (head.version == CWORD_LE(0x150)) { offs += 40; } else { return (NULL); } /* 定位到已知数据区域 */ if (!CR_VCALL(datin)->seek(datin, offs, SEEK_SET)) return (NULL); /* 读取所有帧属性数据 */ head.img_num = DWORD_LE(head.img_num); attr = mem_talloc32(head.img_num, sAIA_IDX); if (attr == NULL) return (NULL); /* 准备好一些属性值 */ ww = WORD_LE(head.ww1); hh = WORD_LE(head.hh1); head.pal_num = DWORD_LE(head.pal_num); head.img_size = DWORD_LE(head.img_size); /* 逐个读入有效的帧属性 */ for (cnt = idx = 0; idx < head.img_num; idx++) { back = CR_VCALL(datin)->read(datin, &attr[cnt], sizeof(sAIA_IDX)); if (back != sizeof(sAIA_IDX)) goto _failure1; /* 跳过非法的废帧 */ attr[cnt].offset = DWORD_LE(attr[cnt].offset); if (attr[cnt].offset >= head.img_size) continue; attr[cnt].pal_idx = WORD_LE(attr[cnt].pal_idx); if ((int32u)attr[cnt].pal_idx >= head.pal_num) continue; /* 跳过废帧 (请自己定义帧序号) */ attr[cnt].x1 = WORD_LE(attr[cnt].x1); attr[cnt].y1 = WORD_LE(attr[cnt].y1); attr[cnt].x2 = WORD_LE(attr[cnt].x2); attr[cnt].y2 = WORD_LE(attr[cnt].y2); if ((uint_t)attr[cnt].x2 > ww || (uint_t)attr[cnt].y2 > hh || attr[cnt].x1 >= attr[cnt].x2 || attr[cnt].y1 >= attr[cnt].y2) continue; attr[cnt].x2 = attr[cnt].x2 - attr[cnt].x1; attr[cnt].y2 = attr[cnt].y2 - attr[cnt].y1; cnt += 1; } /* 空图片检查 */ if (cnt == 0) goto _failure1; /* 读取所有调色板数据 */ pals = (byte_t*)mem_calloc32(head.pal_num, 1024); if (pals == NULL) goto _failure1; size = (leng_t)head.pal_num; size *= 1024; if (CR_VCALL(datin)->read(datin, pals, size) != size) goto _failure2; for (back = 0; back < size; back += 4) pals[back + 3] = 0xFF; /* 读取所有图形数据 */ dats = (byte_t*)mem_malloc32(head.img_size); if (dats == NULL) goto _failure2; size = (leng_t)head.img_size; if (CR_VCALL(datin)->read(datin, dats, size) != size) goto _failure3; /* 生成多帧图片接口对象 */ port = struct_new(iPIC_AIA); if (port == NULL) goto _failure3; port->m_ww = ww; port->m_hh = hh; port->m_attr = attr; port->m_dats = dats; port->m_pals = (int32u*)pals; port->m_size = head.img_size; port->pics.__count__ = cnt; port->pics.__vptr__ = &s_pics_vtbl; /* 返回读取的文件数据 */ rett = struct_new(sFMT_PRT); if (rett == NULL) { iPIC_AIA_release((iPICTURE*)port); return (NULL); } CR_NOUSE(param); rett->type = CR_FMTZ_PRT; rett->port = (iPORT*)port; rett->more = "iPICTURE"; rett->infor = "FALCOM YS AIA Image File (*.AIA)"; return (rett); _failure3: mem_free(dats); _failure2: mem_free(pals); _failure1: mem_free(attr); return (NULL); }
/* ======================================= SPB (BMP) 解压缩 ======================================= */ CR_API leng_t decode_spb ( __CR_OT__ void_t* dst, __CR_IN__ leng_t dstlen, __CR_IN__ const void_t* src, __CR_IN__ leng_t srclen ) { int32u vals; byte_t* copy; byte_t* line; byte_t* image; sBITIN bitin; iDATIN* datin; leng_t count; uint_t ii, jj; uint_t mm, nn; uint_t cc, kk; int16u ww, hh; byte_t* channel; leng_t img_size; leng_t bmp_size; leng_t bpl, size; /* 建立位流输入对象 */ datin = create_buff_in(src, srclen, FALSE); if (datin == NULL) return (0); bitin_init(&bitin, datin, sizeof(byte_t)); /* 读取图片宽高 */ if (!CR_VCALL(datin)->getw_be(datin, &ww)) goto _failure1; if (!CR_VCALL(datin)->getw_be(datin, &hh)) goto _failure1; if (cut_mul(&bpl, ww, 3)) goto _failure1; size = (leng_t)CR_PADDED(bpl, 4); if (cut_addu(&bpl, bpl, size)) goto _failure1; if (cut_mul(&img_size, bpl, hh)) goto _failure1; if (cut_addu(&bmp_size, img_size, sizeof(s_bmp))) goto _failure1; /* 安全检查 */ if (dstlen < bmp_size) goto _failure1; mem_cpy(dst, s_bmp, sizeof(s_bmp)); image = (byte_t*)dst + sizeof(s_bmp); /* 生成一个颜色通道的缓存 */ size = ww; size *= hh; channel = (byte_t*)mem_malloc(size + 4); if (channel == NULL) goto _failure1; /* 是三个通道分开压缩的 */ for (ii = 0; ii < 3; ii++) { count = 0; if (!bitin_hi_push(&bitin, &cc, 8)) goto _failure2; /* 解码一个颜色通道 */ channel[count++] = (byte_t)cc; while (count < size) { if (!bitin_hi_push(&bitin, &nn, 3)) goto _failure2; if (nn == 0) { channel[count++] = (byte_t)cc; channel[count++] = (byte_t)cc; channel[count++] = (byte_t)cc; channel[count++] = (byte_t)cc; continue; } if (nn == 7) { if (!bitin_hi_push(&bitin, &mm, 1)) goto _failure2; mm += 1; } else { mm = nn + 2; } for (jj = 0; jj < 4; jj++) { if (mm == 8) { if (!bitin_hi_push(&bitin, &cc, 8)) goto _failure2; } else { if (!bitin_hi_push(&bitin, &kk, mm)) goto _failure2; if (kk & 1) cc += (kk >> 1) + 1; else cc -= (kk >> 1); } channel[count++] = (byte_t)cc; } } /* 颜色通道填充到图片数据 */ line = image + bpl * (hh - 1) + ii; copy = channel; for (jj = 0; jj < (uint_t)hh; jj++) { if (jj & 1) { for (kk = 0; kk < (uint_t)ww; kk++, line -= 3) *line = *copy++; line -= bpl - 3; } else { for (kk = 0; kk < (uint_t)ww; kk++, line += 3) *line = *copy++; line -= bpl + 3; } } }
/* --------------------------------------- 绘制文字 (内部实现) --------------------------------------- */ static bool_t qst_crh_text_int ( __CR_IN__ sIMAGE* draw, __CR_IN__ bool_t tran, __CR_IN__ const sRECT* rect, __CR_IN__ const ansi_t* text, __CR_IN__ uint_t align ) { sBLIT blit; iGFX2* gfx2; int32u mode; sIMAGE temp, *surf; bool_t rett = FALSE; /* GDI 文字绘制对象要特殊处理 */ if (is_gdi_text_out()) { /* 创建一个临时 GDI 表面然后复制输出的结果到目标画布 */ gfx2 = (iGFX2*)s_gdi_calls->create_bitmap(draw->position.ww, draw->position.hh, CR_ARGB8888); if (gfx2 == NULL) return (FALSE); /* 画布复制到临时 GDI 表面 */ blit.dx = blit.dy = 0; blit.sx = blit.sy = 0; blit.sw = draw->position.ww; blit.sh = draw->position.hh; surf = CR_VCALL(gfx2)->lock(gfx2); blit_set32_c(surf, draw, &blit, NULL); CR_VCALL(gfx2)->unlock(gfx2); mode = tran ? TRANSPARENT : OPAQUE; /* 绑定目标表面并输出文字 */ if (CR_VCALL(s_font)->bind(s_font, gfx2) && CR_VCALL(s_font)->setMode(s_font, mode) && CR_VCALL(s_font)->setColor(s_font, s_color.val) && CR_VCALL(s_font)->setBkColor(s_font, s_bkcolor.val)) { CR_VCALL(s_font)->enter(s_font); rett = egui_draw_text(s_font, text, rect, align); CR_VCALL(s_font)->leave(s_font); /* 输出结果回拷到目标画布 */ if (rett) { /* 只复制颜色通道 (GDI 会清除 Alpha 通道) */ surf = CR_VCALL(gfx2)->lock(gfx2); image_flp(surf, FALSE); for (leng_t idx = 0; idx < draw->size; idx += 4) { draw->data[idx + 0] = surf->data[idx + 0]; draw->data[idx + 1] = surf->data[idx + 1]; draw->data[idx + 2] = surf->data[idx + 2]; } CR_VCALL(gfx2)->unlock(gfx2); } } } else { /* 随便生成一个内存绘制表面然后替换其后台缓冲结构为画布 */ gfx2 = create_mem_bitmap(1, 1, CR_ARGB8888); if (gfx2 == NULL) return (FALSE); /* 替换表面参数结构 */ struct_cpy(&temp, &gfx2->__back__, sIMAGE); struct_cpy(&gfx2->__back__, draw, sIMAGE); /* 绑定目标表面并输出文字 */ if (CR_VCALL(s_font)->bind(s_font, gfx2) && CR_VCALL(s_font)->setMode(s_font, s_mode) && CR_VCALL(s_font)->setColor(s_font, s_color.val) && CR_VCALL(s_font)->setBkColor(s_font, s_bkcolor.val)) { if (tran) rett = egui_draw_tran(s_font, text, rect, align); else rett = egui_draw_text(s_font, text, rect, align); } /* 换回原来的表面参数 */ struct_cpy(&gfx2->__back__, &temp, sIMAGE); } /* 释放临时表面 */ CR_VCALL(gfx2)->release(gfx2); return (rett); }
/* --------------------------------------- 设置模式 --------------------------------------- */ static bool_t qst_crh_mode ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { CR_NOUSE(parm); /* 参数解析 <Mode> */ if (argc < 2) return (FALSE); if (str_cmpIA(argv[1], "set") == 0) { s_mode = CR_BLT_SET; s_pixdraw = pixel_set32z; s_flldraw = fill_set32_c; } else if (str_cmpIA(argv[1], "lrp") == 0) { s_mode = CR_BLT_ALP; s_pixdraw = pixel_lrp32z; s_flldraw = fill_lrp32_c; } else if (str_cmpIA(argv[1], "add") == 0) { s_mode = CR_BLT_ADD; s_pixdraw = pixel_add32z; s_flldraw = fill_add32_c; } else if (str_cmpIA(argv[1], "sub") == 0) { s_mode = CR_BLT_SUB; s_pixdraw = pixel_sub32z; s_flldraw = fill_sub32_c; } else if (str_cmpIA(argv[1], "xor") == 0) { s_mode = CR_BLT_XOR; s_pixdraw = pixel_xor32z; s_flldraw = fill_xor32_c; } else if (str_cmpIA(argv[1], "and") == 0) { s_mode = CR_BLT_AND; s_pixdraw = pixel_and32z; s_flldraw = fill_and32_c; } else if (str_cmpIA(argv[1], "orr") == 0) { s_mode = CR_BLT_ORR; s_pixdraw = pixel_orr32z; s_flldraw = fill_orr32_c; } else if (str_cmpIA(argv[1], "not") == 0) { s_mode = CR_BLT_NOT; s_pixdraw = pixel_not32z; s_flldraw = fill_not32_c; } else { return (FALSE); } if (s_font == NULL) return (TRUE); if (is_gdi_text_out()) return (TRUE); return (CR_VCALL(s_font)->setMode(s_font, s_mode)); }
/* ======================================= TGL CGR 文件读取 ======================================= */ CR_API sFMT_PIC* load_tgl_cgr ( __CR_IO__ iDATIN* datin, __CR_IN__ const sLOADER* param ) { int32u wnh[2]; uint_t ww, hh; /*************/ byte_t* line; fsize_t size; sFMT_PIC* rett; sFMT_FRAME temp; /* 这个参数可能为空 */ if (datin == NULL) return (NULL); /* 只能根据文件大小来判断 */ size = dati_get_size(datin); if (size <= 0x600 + 12) return (NULL); if (!CR_VCALL(datin)->seek(datin, 0x600, SEEK_SET)) return (NULL); if (CR_VCALL(datin)->read(datin, wnh, 8) != 8) return (NULL); wnh[0] = DWORD_LE(wnh[0]); wnh[1] = DWORD_LE(wnh[1]); size = wnh[0]; size *= wnh[1]; size += 0x600 + 12; if (size != dati_get_size(datin)) return (NULL); /* 对宽高的截断检查 */ if (cut_int32_u(&ww, wnh[0])) return (NULL); if (cut_int32_u(&hh, wnh[1])) return (NULL); /* 定位到调色板 */ if (!CR_VCALL(datin)->rewind(datin)) return (NULL); /* 生成图片对象 */ mem_zero(temp.wh, sizeof(temp.wh)); temp.fmt = CR_PIC_PALS; temp.bpp = 8; temp.clr = "P"; temp.wh[0] = 8; temp.pic = image_new(0, 0, ww, hh, CR_INDEX8, FALSE, 4); if (temp.pic == NULL) return (NULL); /* 读取调色板数据 */ if (CR_VCALL(datin)->read(datin, temp.pic->pal, 1024) != 1024) goto _failure; line = temp.pic->data; pal_4b_alp_sw(temp.pic->pal, TRUE, 0xFF, 256); /* 定位到图片数据 */ if (!CR_VCALL(datin)->seek(datin, 0x600 + 12, SEEK_SET)) goto _failure; /* 读取图片数据 */ for (; hh != 0; hh--) { if (CR_VCALL(datin)->read(datin, line, ww) != ww) goto _failure; line += temp.pic->bpl; } /* 返回读取的文件数据 */ rett = struct_new(sFMT_PIC); if (rett == NULL) goto _failure; rett->frame = struct_dup(&temp, sFMT_FRAME); if (rett->frame == NULL) { mem_free(rett); goto _failure; } CR_NOUSE(param); rett->type = CR_FMTZ_PIC; rett->count = 1; rett->infor = "TGL CGR Image File (CGR)"; return (rett); _failure: image_del(temp.pic); return (NULL); }