void
make_T_Table(char *table, const PRUint8 Sx[256], FILE *file,
             unsigned char m0, unsigned char m1, 
             unsigned char m2, unsigned char m3)
{
    PRUint32 Ti;
    int i;
    fprintf(file, "#ifdef IS_LITTLE_ENDIAN\n");
    fprintf(file, "static const PRUint32 _T%s[256] = \n{\n", table);
    for (i=0; i<256; i++) {
	Ti = WORD_LE( gf_multiply(Sx[i], m0),
	              gf_multiply(Sx[i], m1),
	              gf_multiply(Sx[i], m2),
	              gf_multiply(Sx[i], m3) );
	if (Ti == 0)
	    fprintf(file, "0x00000000%c%c", (i==255)?' ':',',
	                                    (i%6==5)?'\n':' ');
	else
	    fprintf(file, "%#.8x%c%c", Ti, (i==255)?' ':',',
	                                   (i%6==5)?'\n':' ');
    }
    fprintf(file, "\n};\n");
    fprintf(file, "#else\n");
    fprintf(file, "static const PRUint32 _T%s[256] = \n{\n", table);
    for (i=0; i<256; i++) {
	Ti = WORD_BE( gf_multiply(Sx[i], m0),
	              gf_multiply(Sx[i], m1),
	              gf_multiply(Sx[i], m2),
	              gf_multiply(Sx[i], m3) );
	if (Ti == 0)
	    fprintf(file, "0x00000000%c%c", (i==255)?' ':',',
	                                    (i%6==5)?'\n':' ');
	else
	    fprintf(file, "%#.8x%c%c", Ti, (i==255)?' ':',',
	                                   (i%6==5)?'\n':' ');
    }
    fprintf(file, "\n};\n");
    fprintf(file, "#endif\n\n");
}
Beispiel #2
0
/*
=======================================
    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);
}
Beispiel #3
0
/*
=======================================
    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);
}
Beispiel #4
0
/*
=======================================
    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);
}
int main()
{
    int i, j;
    PRUint8 cur, last;
    PRUint32 tmp;
    FILE *optfile;
    optfile = fopen("rijndael32.tab", "w");
    /* output S, if there are no T tables */
    fprintf(optfile, "#ifndef RIJNDAEL_INCLUDE_TABLES\n");
    fprintf(optfile, "static const PRUint8 _S[256] = \n{\n");
    for (i=0; i<256; i++) {
	fprintf(optfile, "%3d%c%c", __S[i],(i==255)?' ':',', 
	                            (i%16==15)?'\n':' ');
    }
    fprintf(optfile, "};\n#endif /* not RIJNDAEL_INCLUDE_TABLES */\n\n");
    /* output S**-1 */
    fprintf(optfile, "static const PRUint8 _SInv[256] = \n{\n");
    for (i=0; i<256; i++) {
	fprintf(optfile, "%3d%c%c", __SInv[i],(i==255)?' ':',', 
	                            (i%16==15)?'\n':' ');
    }
    fprintf(optfile, "};\n\n");
    fprintf(optfile, "#ifdef RIJNDAEL_INCLUDE_TABLES\n");
    /* The 32-bit word tables for optimized implementation */
    /* T0 = [ S[a] * 02, S[a], S[a], S[a] * 03 ] */
    make_T_Table("0", __S, optfile, 0x02, 0x01, 0x01, 0x03);
    /* T1 = [ S[a] * 03, S[a] * 02, S[a], S[a] ] */
    make_T_Table("1", __S, optfile, 0x03, 0x02, 0x01, 0x01);
    /* T2 = [ S[a], S[a] * 03, S[a] * 02, S[a] ] */
    make_T_Table("2", __S, optfile, 0x01, 0x03, 0x02, 0x01);
    /* T3 = [ S[a], S[a], S[a] * 03, S[a] * 02 ] */
    make_T_Table("3", __S, optfile, 0x01, 0x01, 0x03, 0x02);
    /* TInv0 = [ Si[a] * 0E, Si[a] * 09, Si[a] * 0D, Si[a] * 0B ] */
    make_T_Table("Inv0", __SInv, optfile, 0x0e, 0x09, 0x0d, 0x0b);
    /* TInv1 = [ Si[a] * 0B, Si[a] * 0E, Si[a] * 09, Si[a] * 0D ] */
    make_T_Table("Inv1", __SInv, optfile, 0x0b, 0x0e, 0x09, 0x0d);
    /* TInv2 = [ Si[a] * 0D, Si[a] * 0B, Si[a] * 0E, Si[a] * 09 ] */
    make_T_Table("Inv2", __SInv, optfile, 0x0d, 0x0b, 0x0e, 0x09);
    /* TInv3 = [ Si[a] * 09, Si[a] * 0D, Si[a] * 0B, Si[a] * 0E ] */
    make_T_Table("Inv3", __SInv, optfile, 0x09, 0x0d, 0x0b, 0x0e);
    /* byte multiply tables for inverse key expansion (mimics InvMixColumn) */
    make_InvMixCol_Table(0, optfile, 0x0e, 0x09, 0x0d, 0x0b);
    make_InvMixCol_Table(1, optfile, 0x0b, 0x0E, 0x09, 0x0d);
    make_InvMixCol_Table(2, optfile, 0x0d, 0x0b, 0x0e, 0x09);
    make_InvMixCol_Table(3, optfile, 0x09, 0x0d, 0x0b, 0x0e);
    fprintf(optfile, "#endif /* RIJNDAEL_INCLUDE_TABLES */\n\n");
    /* round constants for key expansion */
    fprintf(optfile, "#ifdef IS_LITTLE_ENDIAN\n");
    fprintf(optfile, "static const PRUint32 Rcon[30] = {\n");
    cur = 0x01;
    for (i=0; i<30; i++) {
	fprintf(optfile, "%#.8x%c%c", WORD_LE(cur, 0, 0, 0), 
	                                (i==29)?' ':',', (i%6==5)?'\n':' ');
	last = cur;
	cur = gf_multiply(last, 0x02);
    }
    fprintf(optfile, "};\n");
    fprintf(optfile, "#else\n");
    fprintf(optfile, "static const PRUint32 Rcon[30] = {\n");
    cur = 0x01;
    for (i=0; i<30; i++) {
	fprintf(optfile, "%#.8x%c%c", WORD_BE(cur, 0, 0, 0), 
	                                (i==29)?' ':',', (i%6==5)?'\n':' ');
	last = cur;
	cur = gf_multiply(last, 0x02);
    }
    fprintf(optfile, "};\n");
    fprintf(optfile, "#endif\n\n");
    fclose(optfile);
    return 0;
}
Beispiel #6
0
                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;
            }
        }
    }

    /* 填写 BMP 图片信息 */
    vals = DWORD_LE((int32u)bmp_size);
    mem_cpy((byte_t*)dst + 2, &vals, 4);
    ww = WORD_LE(ww);
    mem_cpy((byte_t*)dst + 18, &ww, 2);
    hh = WORD_LE(hh);
    mem_cpy((byte_t*)dst + 22, &hh, 2);
    vals = DWORD_LE((int32u)img_size);
    mem_cpy((byte_t*)dst + 34, &vals, 4);
    mem_free(channel);
    CR_VCALL(datin)->release(datin);
    return (bmp_size);

_failure2:
    mem_free(channel);
_failure1:
    CR_VCALL(datin)->release(datin);
    return (0);
}