static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y,

                             const uint8_t *src, int src_size)

{

    int width, height;

    int hdr, zsize, npal, tidx = -1, ret;

    int i, j;

    const uint8_t *src_end = src + src_size;

    uint8_t pal[768], transp[3];

    uLongf dlen = (c->tile_width + 1) * c->tile_height;

    int sub_type;

    int nblocks, cblocks, bstride;

    int bits, bitbuf, coded;

    uint8_t *dst = c->framebuf + tile_x * c->tile_width * 3 +

                   tile_y * c->tile_height * c->framebuf_stride;



    if (src_size < 2)

        return AVERROR_INVALIDDATA;



    width  = FFMIN(c->width  - tile_x * c->tile_width,  c->tile_width);

    height = FFMIN(c->height - tile_y * c->tile_height, c->tile_height);



    hdr = *src++;

    sub_type = hdr >> 5;

    if (sub_type == 0) {

        int j;

        memcpy(transp, src, 3);

        src += 3;

        for (j = 0; j < height; j++, dst += c->framebuf_stride)

            for (i = 0; i < width; i++)

                memcpy(dst + i * 3, transp, 3);

        return 0;

    } else if (sub_type == 1) {

        return jpg_decode_data(&c->jc, width, height, src, src_end - src,

                               dst, c->framebuf_stride, NULL, 0, 0, 0);

    }



    if (sub_type != 2) {

        memcpy(transp, src, 3);

        src += 3;

    }

    npal = *src++ + 1;

    memcpy(pal, src, npal * 3); src += npal * 3;

    if (sub_type != 2) {

        for (i = 0; i < npal; i++) {

            if (!memcmp(pal + i * 3, transp, 3)) {

               tidx = i;

               break;

            }

        }

    }



    if (src_end - src < 2)

        return 0;

    zsize = (src[0] << 8) | src[1]; src += 2;



    if (src_end - src < zsize)

        return AVERROR_INVALIDDATA;



    ret = uncompress(c->kempf_buf, &dlen, src, zsize);

    if (ret)

        return AVERROR_INVALIDDATA;

    src += zsize;



    if (sub_type == 2) {

        kempf_restore_buf(c->kempf_buf, dlen, dst, c->framebuf_stride,

                          NULL, 0, width, height, pal, npal, tidx);

        return 0;

    }



    nblocks = *src++ + 1;

    cblocks = 0;

    bstride = FFALIGN(width, 16) >> 4;

    // blocks are coded LSB and we need normal bitreader for JPEG data

    bits = 0;

    for (i = 0; i < (FFALIGN(height, 16) >> 4); i++) {

        for (j = 0; j < (FFALIGN(width, 16) >> 4); j++) {

            if (!bits) {

                bitbuf = *src++;

                bits   = 8;

            }

            coded = bitbuf & 1;

            bits--;

            bitbuf >>= 1;

            cblocks += coded;

            if (cblocks > nblocks)

                return AVERROR_INVALIDDATA;

            c->kempf_flags[j + i * bstride] = coded;

        }

    }



    memset(c->jpeg_tile, 0, c->tile_stride * height);

    jpg_decode_data(&c->jc, width, height, src, src_end - src,

                    c->jpeg_tile, c->tile_stride,

                    c->kempf_flags, bstride, nblocks, 0);



    kempf_restore_buf(c->kempf_buf, dlen, dst, c->framebuf_stride,

                      c->jpeg_tile, c->tile_stride,

                      width, height, pal, npal, tidx);



    return 0;

}

static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y,

                             const uint8_t *src, int src_size)

{

    int width, height;

    int hdr, zsize, npal, tidx = -1, ret;

    int i, j;

    const uint8_t *src_end = src + src_size;

    uint8_t pal[768], transp[3];

    uLongf dlen = (c->tile_width + 1) * c->tile_height;

    int sub_type;

    int nblocks, cblocks, bstride;

    int bits, bitbuf, coded;

    uint8_t *dst = c->framebuf + tile_x * c->tile_width * 3 +

                   tile_y * c->tile_height * c->framebuf_stride;



    if (src_size < 2)

        return AVERROR_INVALIDDATA;



    width  = FFMIN(c->width  - tile_x * c->tile_width,  c->tile_width);

    height = FFMIN(c->height - tile_y * c->tile_height, c->tile_height);



    hdr = *src++;

    sub_type = hdr >> 5;

    if (sub_type == 0) {

        int j;

        memcpy(transp, src, 3);

        src += 3;

        for (j = 0; j < height; j++, dst += c->framebuf_stride)

            for (i = 0; i < width; i++)

                memcpy(dst + i * 3, transp, 3);

        return 0;

    } else if (sub_type == 1) {

        return jpg_decode_data(&c->jc, width, height, src, src_end - src,

                               dst, c->framebuf_stride, NULL, 0, 0, 0);

    }



    if (sub_type != 2) {

        memcpy(transp, src, 3);

        src += 3;

    }

    npal = *src++ + 1;

    memcpy(pal, src, npal * 3); src += npal * 3;

    if (sub_type != 2) {

        for (i = 0; i < npal; i++) {

            if (!memcmp(pal + i * 3, transp, 3)) {

               tidx = i;

               break;

            }

        }

    }



    if (src_end - src < 2)

        return 0;

    zsize = (src[0] << 8) | src[1]; src += 2;



    if (src_end - src < zsize)

        return AVERROR_INVALIDDATA;



    ret = uncompress(c->kempf_buf, &dlen, src, zsize);

    if (ret)

        return AVERROR_INVALIDDATA;

    src += zsize;



    if (sub_type == 2) {

        kempf_restore_buf(c->kempf_buf, dlen, dst, c->framebuf_stride,

                          NULL, 0, width, height, pal, npal, tidx);

        return 0;

    }



    nblocks = *src++ + 1;

    cblocks = 0;

    bstride = FFALIGN(width, 16) >> 4;

    

    bits = 0;

    for (i = 0; i < (FFALIGN(height, 16) >> 4); i++) {

        for (j = 0; j < (FFALIGN(width, 16) >> 4); j++) {

            if (!bits) {

                bitbuf = *src++;

                bits   = 8;

            }

            coded = bitbuf & 1;

            bits--;

            bitbuf >>= 1;

            cblocks += coded;

            if (cblocks > nblocks)

                return AVERROR_INVALIDDATA;

            c->kempf_flags[j + i * bstride] = coded;

        }

    }



    memset(c->jpeg_tile, 0, c->tile_stride * height);

    jpg_decode_data(&c->jc, width, height, src, src_end - src,

                    c->jpeg_tile, c->tile_stride,

                    c->kempf_flags, bstride, nblocks, 0);



    kempf_restore_buf(c->kempf_buf, dlen, dst, c->framebuf_stride,

                      c->jpeg_tile, c->tile_stride,

                      width, height, pal, npal, tidx);



    return 0;

}

static int FUNC_0(G2MContext *VAR_0, int VAR_1, int VAR_2,

                             const uint8_t *VAR_3, int VAR_4)

{

    int VAR_5, VAR_6;

    int VAR_7, VAR_8, VAR_9, VAR_10 = -1, VAR_11;

    int VAR_12, VAR_22;

    const uint8_t *VAR_14 = VAR_3 + VAR_4;

    uint8_t pal[768], transp[3];

    uLongf dlen = (VAR_0->tile_width + 1) * VAR_0->tile_height;

    int VAR_15;

    int VAR_16, VAR_17, VAR_18;

    int VAR_19, VAR_20, VAR_21;

    uint8_t *dst = VAR_0->framebuf + VAR_1 * VAR_0->tile_width * 3 +

                   VAR_2 * VAR_0->tile_height * VAR_0->framebuf_stride;



    if (VAR_4 < 2)

        return AVERROR_INVALIDDATA;



    VAR_5  = FFMIN(VAR_0->VAR_5  - VAR_1 * VAR_0->tile_width,  VAR_0->tile_width);

    VAR_6 = FFMIN(VAR_0->VAR_6 - VAR_2 * VAR_0->tile_height, VAR_0->tile_height);



    VAR_7 = *VAR_3++;

    VAR_15 = VAR_7 >> 5;

    if (VAR_15 == 0) {

        int VAR_22;

        memcpy(transp, VAR_3, 3);

        VAR_3 += 3;

        for (VAR_22 = 0; VAR_22 < VAR_6; VAR_22++, dst += VAR_0->framebuf_stride)

            for (VAR_12 = 0; VAR_12 < VAR_5; VAR_12++)

                memcpy(dst + VAR_12 * 3, transp, 3);

        return 0;

    } else if (VAR_15 == 1) {

        return jpg_decode_data(&VAR_0->jc, VAR_5, VAR_6, VAR_3, VAR_14 - VAR_3,

                               dst, VAR_0->framebuf_stride, NULL, 0, 0, 0);

    }



    if (VAR_15 != 2) {

        memcpy(transp, VAR_3, 3);

        VAR_3 += 3;

    }

    VAR_9 = *VAR_3++ + 1;

    memcpy(pal, VAR_3, VAR_9 * 3); VAR_3 += VAR_9 * 3;

    if (VAR_15 != 2) {

        for (VAR_12 = 0; VAR_12 < VAR_9; VAR_12++) {

            if (!memcmp(pal + VAR_12 * 3, transp, 3)) {

               VAR_10 = VAR_12;

               break;

            }

        }

    }



    if (VAR_14 - VAR_3 < 2)

        return 0;

    VAR_8 = (VAR_3[0] << 8) | VAR_3[1]; VAR_3 += 2;



    if (VAR_14 - VAR_3 < VAR_8)

        return AVERROR_INVALIDDATA;



    VAR_11 = uncompress(VAR_0->kempf_buf, &dlen, VAR_3, VAR_8);

    if (VAR_11)

        return AVERROR_INVALIDDATA;

    VAR_3 += VAR_8;



    if (VAR_15 == 2) {

        kempf_restore_buf(VAR_0->kempf_buf, dlen, dst, VAR_0->framebuf_stride,

                          NULL, 0, VAR_5, VAR_6, pal, VAR_9, VAR_10);

        return 0;

    }



    VAR_16 = *VAR_3++ + 1;

    VAR_17 = 0;

    VAR_18 = FFALIGN(VAR_5, 16) >> 4;

    

    VAR_19 = 0;

    for (VAR_12 = 0; VAR_12 < (FFALIGN(VAR_6, 16) >> 4); VAR_12++) {

        for (VAR_22 = 0; VAR_22 < (FFALIGN(VAR_5, 16) >> 4); VAR_22++) {

            if (!VAR_19) {

                VAR_20 = *VAR_3++;

                VAR_19   = 8;

            }

            VAR_21 = VAR_20 & 1;

            VAR_19--;

            VAR_20 >>= 1;

            VAR_17 += VAR_21;

            if (VAR_17 > VAR_16)

                return AVERROR_INVALIDDATA;

            VAR_0->kempf_flags[VAR_22 + VAR_12 * VAR_18] = VAR_21;

        }

    }



    memset(VAR_0->jpeg_tile, 0, VAR_0->tile_stride * VAR_6);

    jpg_decode_data(&VAR_0->jc, VAR_5, VAR_6, VAR_3, VAR_14 - VAR_3,

                    VAR_0->jpeg_tile, VAR_0->tile_stride,

                    VAR_0->kempf_flags, VAR_18, VAR_16, 0);



    kempf_restore_buf(VAR_0->kempf_buf, dlen, dst, VAR_0->framebuf_stride,

                      VAR_0->jpeg_tile, VAR_0->tile_stride,

                      VAR_5, VAR_6, pal, VAR_9, VAR_10);



    return 0;

}

static int FUNC_0(G2MContext *VAR_0, int VAR_1, int VAR_2,
const uint8_t *VAR_3, int VAR_4)
{ int VAR_5, VAR_6; int VAR_7, VAR_8, VAR_9, VAR_10 = -1, VAR_11; int VAR_12, VAR_22; const uint8_t *VAR_14 = VAR_3 + VAR_4; uint8_t pal[768], transp[3]; uLongf dlen = (VAR_0->tile_width + 1) * VAR_0->tile_height; int VAR_15; int VAR_16, VAR_17, VAR_18; int VAR_19, VAR_20, VAR_21; uint8_t *dst = VAR_0->framebuf + VAR_1 * VAR_0->tile_width * 3 +
VAR_2 * VAR_0->tile_height * VAR_0->framebuf_stride; if (VAR_4 < 2)
return AVERROR_INVALIDDATA; VAR_5  = FFMIN(VAR_0->VAR_5  - VAR_1 * VAR_0->tile_width,  VAR_0->tile_width); VAR_6 = FFMIN(VAR_0->VAR_6 - VAR_2 * VAR_0->tile_height, VAR_0->tile_height); VAR_7 = *VAR_3++; VAR_15 = VAR_7 >> 5; if (VAR_15 == 0) { int VAR_22; memcpy(transp, VAR_3, 3); VAR_3 += 3; for (VAR_22 = 0; VAR_22 < VAR_6; VAR_22++, dst += VAR_0->framebuf_stride) for (VAR_12 = 0; VAR_12 < VAR_5; VAR_12++) memcpy(dst + VAR_12 * 3, transp, 3); return 0; } else if (VAR_15 == 1) { return jpg_decode_data(&VAR_0->jc, VAR_5, VAR_6, VAR_3, VAR_14 - VAR_3,
dst, VAR_0->framebuf_stride, NULL, 0, 0, 0); } if (VAR_15 != 2) { memcpy(transp, VAR_3, 3); VAR_3 += 3; } VAR_9 = *VAR_3++ + 1; memcpy(pal, VAR_3, VAR_9 * 3); VAR_3 += VAR_9 * 3; if (VAR_15 != 2) { for (VAR_12 = 0; VAR_12 < VAR_9; VAR_12++) { if (!memcmp(pal + VAR_12 * 3, transp, 3)) { VAR_10 = VAR_12; break; } } } if (VAR_14 - VAR_3 < 2)
return 0; VAR_8 = (VAR_3[0] << 8) | VAR_3[1]; VAR_3 += 2; if (VAR_14 - VAR_3 < VAR_8)
return AVERROR_INVALIDDATA; VAR_11 = uncompress(VAR_0->kempf_buf, &dlen, VAR_3, VAR_8); if (VAR_11)
return AVERROR_INVALIDDATA; VAR_3 += VAR_8; if (VAR_15 == 2) { kempf_restore_buf(VAR_0->kempf_buf, dlen, dst, VAR_0->framebuf_stride,
NULL, 0, VAR_5, VAR_6, pal, VAR_9, VAR_10); return 0; } VAR_16 = *VAR_3++ + 1; VAR_17 = 0; VAR_18 = FFALIGN(VAR_5, 16) >> 4; VAR_19 = 0; for (VAR_12 = 0; VAR_12 < (FFALIGN(VAR_6, 16) >> 4); VAR_12++) { for (VAR_22 = 0; VAR_22 < (FFALIGN(VAR_5, 16) >> 4); VAR_22++) { if (!VAR_19) { VAR_20 = *VAR_3++; VAR_19   = 8; } VAR_21 = VAR_20 & 1; VAR_19--; VAR_20 >>= 1; VAR_17 += VAR_21; if (VAR_17 > VAR_16)
return AVERROR_INVALIDDATA; VAR_0->kempf_flags[VAR_22 + VAR_12 * VAR_18] = VAR_21; } } memset(VAR_0->jpeg_tile, 0, VAR_0->tile_stride * VAR_6); jpg_decode_data(&VAR_0->jc, VAR_5, VAR_6, VAR_3, VAR_14 - VAR_3,
VAR_0->jpeg_tile, VAR_0->tile_stride,
VAR_0->kempf_flags, VAR_18, VAR_16, 0); kempf_restore_buf(VAR_0->kempf_buf, dlen, dst, VAR_0->framebuf_stride,
VAR_0->jpeg_tile, VAR_0->tile_stride,
VAR_5, VAR_6, pal, VAR_9, VAR_10); return 0; }