static int decode_bmv_frame(const uint8_t *source, int src_len, uint8_t *frame, int frame_off)

{

    unsigned val, saved_val = 0;

    int tmplen = src_len;

    const uint8_t *src, *source_end = source + src_len;

    uint8_t *frame_end = frame + SCREEN_WIDE * SCREEN_HIGH;

    uint8_t *dst, *dst_end;

    int len, mask;

    int forward = (frame_off <= -SCREEN_WIDE) || (frame_off >= 0);

    int read_two_nibbles, flag;

    int advance_mode;

    int mode = 0;

    int i;



    if (src_len <= 0)

        return AVERROR_INVALIDDATA;



    if (forward) {

        src = source;

        dst = frame;

        dst_end = frame_end;

    } else {

        src = source + src_len - 1;

        dst = frame_end - 1;

        dst_end = frame - 1;

    }

    for (;;) {

        int shift = 0;

        flag = 0;



        /* The mode/len decoding is a bit strange:

         * values are coded as variable-length codes with nibble units,

         * code end is signalled by two top bits in the nibble being nonzero.

         * And since data is bytepacked and we read two nibbles at a time,

         * we may get a nibble belonging to the next code.

         * Hence this convoluted loop.

         */

        if (!mode || (tmplen == 4)) {

            if (src < source || src >= source_end)

                return AVERROR_INVALIDDATA;

            val = *src;

            read_two_nibbles = 1;

        } else {

            val = saved_val;

            read_two_nibbles = 0;

        }

        if (!(val & 0xC)) {

            for (;;) {

                if(shift>22)

                    return -1;

                if (!read_two_nibbles) {

                    if (src < source || src >= source_end)

                        return AVERROR_INVALIDDATA;

                    shift += 2;

                    val |= *src << shift;

                    if (*src & 0xC)

                        break;

                }

                // two upper bits of the nibble is zero,

                // so shift top nibble value down into their place

                read_two_nibbles = 0;

                shift += 2;

                mask = (1 << shift) - 1;

                val = ((val >> 2) & ~mask) | (val & mask);

                NEXT_BYTE(src);

                if ((val & (0xC << shift))) {

                    flag = 1;

                    break;

                }

            }

        } else if (mode) {

            flag = tmplen != 4;

        }

        if (flag) {

            tmplen = 4;

        } else {

            saved_val = val >> (4 + shift);

            tmplen = 0;

            val &= (1 << (shift + 4)) - 1;

            NEXT_BYTE(src);

        }

        advance_mode = val & 1;

        len = (val >> 1) - 1;

        av_assert0(len>0);

        mode += 1 + advance_mode;

        if (mode >= 4)

            mode -= 3;

        if (len <= 0 || FFABS(dst_end - dst) < len)

            return AVERROR_INVALIDDATA;

        switch (mode) {

        case 1:

            if (forward) {

                if (dst - frame + SCREEN_WIDE < frame_off ||

                        dst - frame + SCREEN_WIDE + frame_off < 0 ||

                        frame_end - dst < frame_off + len ||

                        frame_end - dst < len)

                    return AVERROR_INVALIDDATA;

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

                    dst[i] = dst[frame_off + i];

                dst += len;

            } else {

                dst -= len;

                if (dst - frame + SCREEN_WIDE < frame_off ||

                        dst - frame + SCREEN_WIDE + frame_off < 0 ||

                        frame_end - dst < frame_off + len ||

                        frame_end - dst < len)

                    return AVERROR_INVALIDDATA;

                for (i = len - 1; i >= 0; i--)

                    dst[i] = dst[frame_off + i];

            }

            break;

        case 2:

            if (forward) {

                if (source + src_len - src < len)

                    return AVERROR_INVALIDDATA;

                memcpy(dst, src, len);

                dst += len;

                src += len;

            } else {

                if (src - source < len)

                    return AVERROR_INVALIDDATA;

                dst -= len;

                src -= len;

                memcpy(dst, src, len);

            }

            break;

        case 3:

            val = forward ? dst[-1] : dst[1];

            if (forward) {

                memset(dst, val, len);

                dst += len;

            } else {

                dst -= len;

                memset(dst, val, len);

            }

            break;

        }

        if (dst == dst_end)

            return 0;

    }

}

static int decode_bmv_frame(const uint8_t *source, int src_len, uint8_t *frame, int frame_off)

{

    unsigned val, saved_val = 0;

    int tmplen = src_len;

    const uint8_t *src, *source_end = source + src_len;

    uint8_t *frame_end = frame + SCREEN_WIDE * SCREEN_HIGH;

    uint8_t *dst, *dst_end;

    int len, mask;

    int forward = (frame_off <= -SCREEN_WIDE) || (frame_off >= 0);

    int read_two_nibbles, flag;

    int advance_mode;

    int mode = 0;

    int i;



    if (src_len <= 0)

        return AVERROR_INVALIDDATA;



    if (forward) {

        src = source;

        dst = frame;

        dst_end = frame_end;

    } else {

        src = source + src_len - 1;

        dst = frame_end - 1;

        dst_end = frame - 1;

    }

    for (;;) {

        int shift = 0;

        flag = 0;



        













        if (!mode || (tmplen == 4)) {

            if (src < source || src >= source_end)

                return AVERROR_INVALIDDATA;

            val = *src;

            read_two_nibbles = 1;

        } else {

            val = saved_val;

            read_two_nibbles = 0;

        }

        if (!(val & 0xC)) {

            for (;;) {

                if(shift>22)

                    return -1;

                if (!read_two_nibbles) {

                    if (src < source || src >= source_end)

                        return AVERROR_INVALIDDATA;

                    shift += 2;

                    val |= *src << shift;

                    if (*src & 0xC)

                        break;

                }

                

                

                read_two_nibbles = 0;

                shift += 2;

                mask = (1 << shift) - 1;

                val = ((val >> 2) & ~mask) | (val & mask);

                NEXT_BYTE(src);

                if ((val & (0xC << shift))) {

                    flag = 1;

                    break;

                }

            }

        } else if (mode) {

            flag = tmplen != 4;

        }

        if (flag) {

            tmplen = 4;

        } else {

            saved_val = val >> (4 + shift);

            tmplen = 0;

            val &= (1 << (shift + 4)) - 1;

            NEXT_BYTE(src);

        }

        advance_mode = val & 1;

        len = (val >> 1) - 1;

        av_assert0(len>0);

        mode += 1 + advance_mode;

        if (mode >= 4)

            mode -= 3;

        if (len <= 0 || FFABS(dst_end - dst) < len)

            return AVERROR_INVALIDDATA;

        switch (mode) {

        case 1:

            if (forward) {

                if (dst - frame + SCREEN_WIDE < frame_off ||

                        dst - frame + SCREEN_WIDE + frame_off < 0 ||

                        frame_end - dst < frame_off + len ||

                        frame_end - dst < len)

                    return AVERROR_INVALIDDATA;

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

                    dst[i] = dst[frame_off + i];

                dst += len;

            } else {

                dst -= len;

                if (dst - frame + SCREEN_WIDE < frame_off ||

                        dst - frame + SCREEN_WIDE + frame_off < 0 ||

                        frame_end - dst < frame_off + len ||

                        frame_end - dst < len)

                    return AVERROR_INVALIDDATA;

                for (i = len - 1; i >= 0; i--)

                    dst[i] = dst[frame_off + i];

            }

            break;

        case 2:

            if (forward) {

                if (source + src_len - src < len)

                    return AVERROR_INVALIDDATA;

                memcpy(dst, src, len);

                dst += len;

                src += len;

            } else {

                if (src - source < len)

                    return AVERROR_INVALIDDATA;

                dst -= len;

                src -= len;

                memcpy(dst, src, len);

            }

            break;

        case 3:

            val = forward ? dst[-1] : dst[1];

            if (forward) {

                memset(dst, val, len);

                dst += len;

            } else {

                dst -= len;

                memset(dst, val, len);

            }

            break;

        }

        if (dst == dst_end)

            return 0;

    }

}

                    val |= *src << shift;
static int FUNC_0(const uint8_t *VAR_0, int VAR_1, uint8_t *VAR_2, int VAR_3)

{

    unsigned VAR_4, VAR_5 = 0;

    int VAR_6 = VAR_1;

    const uint8_t *VAR_7, *source_end = VAR_0 + VAR_1;

    uint8_t *frame_end = VAR_2 + SCREEN_WIDE * SCREEN_HIGH;

    uint8_t *dst, *dst_end;

    int VAR_8, VAR_9;

    int VAR_10 = (VAR_3 <= -SCREEN_WIDE) || (VAR_3 >= 0);

    int VAR_11, VAR_12;

    int VAR_13;

    int VAR_14 = 0;

    int VAR_15;



    if (VAR_1 <= 0)

        return AVERROR_INVALIDDATA;



    if (VAR_10) {

        VAR_7 = VAR_0;

        dst = VAR_2;

        dst_end = frame_end;

    } else {

        VAR_7 = VAR_0 + VAR_1 - 1;

        dst = frame_end - 1;

        dst_end = VAR_2 - 1;

    }

    for (;;) {

        int VAR_16 = 0;

        VAR_12 = 0;



        













        if (!VAR_14 || (VAR_6 == 4)) {

            if (VAR_7 < VAR_0 || VAR_7 >= source_end)

                return AVERROR_INVALIDDATA;

            VAR_4 = *VAR_7;

            VAR_11 = 1;

        } else {

            VAR_4 = VAR_5;

            VAR_11 = 0;

        }

        if (!(VAR_4 & 0xC)) {

            for (;;) {

                if(VAR_16>22)

                    return -1;

                if (!VAR_11) {

                    if (VAR_7 < VAR_0 || VAR_7 >= source_end)

                        return AVERROR_INVALIDDATA;

                    VAR_16 += 2;

                    VAR_4 |= *VAR_7 << VAR_16;

                    if (*VAR_7 & 0xC)

                        break;

                }

                

                

                VAR_11 = 0;

                VAR_16 += 2;

                VAR_9 = (1 << VAR_16) - 1;

                VAR_4 = ((VAR_4 >> 2) & ~VAR_9) | (VAR_4 & VAR_9);

                NEXT_BYTE(VAR_7);

                if ((VAR_4 & (0xC << VAR_16))) {

                    VAR_12 = 1;

                    break;

                }

            }

        } else if (VAR_14) {

            VAR_12 = VAR_6 != 4;

        }

        if (VAR_12) {

            VAR_6 = 4;

        } else {

            VAR_5 = VAR_4 >> (4 + VAR_16);

            VAR_6 = 0;

            VAR_4 &= (1 << (VAR_16 + 4)) - 1;

            NEXT_BYTE(VAR_7);

        }

        VAR_13 = VAR_4 & 1;

        VAR_8 = (VAR_4 >> 1) - 1;

        av_assert0(VAR_8>0);

        VAR_14 += 1 + VAR_13;

        if (VAR_14 >= 4)

            VAR_14 -= 3;

        if (VAR_8 <= 0 || FFABS(dst_end - dst) < VAR_8)

            return AVERROR_INVALIDDATA;

        switch (VAR_14) {

        case 1:

            if (VAR_10) {

                if (dst - VAR_2 + SCREEN_WIDE < VAR_3 ||

                        dst - VAR_2 + SCREEN_WIDE + VAR_3 < 0 ||

                        frame_end - dst < VAR_3 + VAR_8 ||

                        frame_end - dst < VAR_8)

                    return AVERROR_INVALIDDATA;

                for (VAR_15 = 0; VAR_15 < VAR_8; VAR_15++)

                    dst[VAR_15] = dst[VAR_3 + VAR_15];

                dst += VAR_8;

            } else {

                dst -= VAR_8;

                if (dst - VAR_2 + SCREEN_WIDE < VAR_3 ||

                        dst - VAR_2 + SCREEN_WIDE + VAR_3 < 0 ||

                        frame_end - dst < VAR_3 + VAR_8 ||

                        frame_end - dst < VAR_8)

                    return AVERROR_INVALIDDATA;

                for (VAR_15 = VAR_8 - 1; VAR_15 >= 0; VAR_15--)

                    dst[VAR_15] = dst[VAR_3 + VAR_15];

            }

            break;

        case 2:

            if (VAR_10) {

                if (VAR_0 + VAR_1 - VAR_7 < VAR_8)

                    return AVERROR_INVALIDDATA;

                memcpy(dst, VAR_7, VAR_8);

                dst += VAR_8;

                VAR_7 += VAR_8;

            } else {

                if (VAR_7 - VAR_0 < VAR_8)

                    return AVERROR_INVALIDDATA;

                dst -= VAR_8;

                VAR_7 -= VAR_8;

                memcpy(dst, VAR_7, VAR_8);

            }

            break;

        case 3:

            VAR_4 = VAR_10 ? dst[-1] : dst[1];

            if (VAR_10) {

                memset(dst, VAR_4, VAR_8);

                dst += VAR_8;

            } else {

                dst -= VAR_8;

                memset(dst, VAR_4, VAR_8);

            }

            break;

        }

        if (dst == dst_end)

            return 0;

    }

}

static int FUNC_0(const uint8_t *VAR_0, int VAR_1, uint8_t *VAR_2, int VAR_3)
{ unsigned VAR_4, VAR_5 = 0; int VAR_6 = VAR_1; const uint8_t *VAR_7, *source_end = VAR_0 + VAR_1; uint8_t *frame_end = VAR_2 + SCREEN_WIDE * SCREEN_HIGH; uint8_t *dst, *dst_end; int VAR_8, VAR_9; int VAR_10 = (VAR_3 <= -SCREEN_WIDE) || (VAR_3 >= 0); int VAR_11, VAR_12; int VAR_13; int VAR_14 = 0; int VAR_15; if (VAR_1 <= 0)
return AVERROR_INVALIDDATA; if (VAR_10) { VAR_7 = VAR_0; dst = VAR_2; dst_end = frame_end; } else { VAR_7 = VAR_0 + VAR_1 - 1; dst = frame_end - 1; dst_end = VAR_2 - 1; } for (;;) { int VAR_16 = 0; VAR_12 = 0; if (!VAR_14 || (VAR_6 == 4)) { if (VAR_7 < VAR_0 || VAR_7 >= source_end)
return AVERROR_INVALIDDATA; VAR_4 = *VAR_7; VAR_11 = 1; } else { VAR_4 = VAR_5; VAR_11 = 0; } if (!(VAR_4 & 0xC)) { for (;;) { if(VAR_16>22)
return -1; if (!VAR_11) { if (VAR_7 < VAR_0 || VAR_7 >= source_end)
return AVERROR_INVALIDDATA; VAR_16 += 2; VAR_4 |= *VAR_7 << VAR_16; if (*VAR_7 & 0xC)
break; } VAR_11 = 0; VAR_16 += 2; VAR_9 = (1 << VAR_16) - 1; VAR_4 = ((VAR_4 >> 2) & ~VAR_9) | (VAR_4 & VAR_9); NEXT_BYTE(VAR_7); if ((VAR_4 & (0xC << VAR_16))) { VAR_12 = 1; break; } } } else if (VAR_14) { VAR_12 = VAR_6 != 4; } if (VAR_12) { VAR_6 = 4; } else { VAR_5 = VAR_4 >> (4 + VAR_16); VAR_6 = 0; VAR_4 &= (1 << (VAR_16 + 4)) - 1; NEXT_BYTE(VAR_7); } VAR_13 = VAR_4 & 1; VAR_8 = (VAR_4 >> 1) - 1; av_assert0(VAR_8>0); VAR_14 += 1 + VAR_13; if (VAR_14 >= 4)
VAR_14 -= 3; if (VAR_8 <= 0 || FFABS(dst_end - dst) < VAR_8)
return AVERROR_INVALIDDATA; switch (VAR_14) { case 1:
if (VAR_10) { if (dst - VAR_2 + SCREEN_WIDE < VAR_3 ||
dst - VAR_2 + SCREEN_WIDE + VAR_3 < 0 ||
frame_end - dst < VAR_3 + VAR_8 ||
frame_end - dst < VAR_8)
return AVERROR_INVALIDDATA; for (VAR_15 = 0; VAR_15 < VAR_8; VAR_15++) dst[VAR_15] = dst[VAR_3 + VAR_15]; dst += VAR_8; } else { dst -= VAR_8; if (dst - VAR_2 + SCREEN_WIDE < VAR_3 ||
dst - VAR_2 + SCREEN_WIDE + VAR_3 < 0 ||
frame_end - dst < VAR_3 + VAR_8 ||
frame_end - dst < VAR_8)
return AVERROR_INVALIDDATA; for (VAR_15 = VAR_8 - 1; VAR_15 >= 0; VAR_15--) dst[VAR_15] = dst[VAR_3 + VAR_15]; } break; case 2:
if (VAR_10) { if (VAR_0 + VAR_1 - VAR_7 < VAR_8)
return AVERROR_INVALIDDATA; memcpy(dst, VAR_7, VAR_8); dst += VAR_8; VAR_7 += VAR_8; } else { if (VAR_7 - VAR_0 < VAR_8)
return AVERROR_INVALIDDATA; dst -= VAR_8; VAR_7 -= VAR_8; memcpy(dst, VAR_7, VAR_8); } break; case 3:
VAR_4 = VAR_10 ? dst[-1] : dst[1]; if (VAR_10) { memset(dst, VAR_4, VAR_8); dst += VAR_8; } else { dst -= VAR_8; memset(dst, VAR_4, VAR_8); } break; } if (dst == dst_end)
return 0; } }