{"name":"Compressed LZO File Format","title":"Compressed LZO File Format","type":"topic","url":"https://community.bistudio.com/wiki/Compressed_LZO_File_Format","revid":373410,"updated":"2025-05-08T11:27:10Z","aliases":[],"markdown":"> **Disclaimer: This page describes internal undocumented structures of Bohemia Interactive software.**\n>\n> This page contains unofficial information.\n>\n> Some usage of this information may constitute a violation of the rights of Bohemia Interactive and is in no way endorsed or recommended by Bohemia Interactive.\n> Bohemia Interactive is not willing to tolerate use of such tools if it contravenes any general licenses granted to end users of this community wiki or BI products.\n\nThis is LZO as defined by oberhumer - http://www.oberhumer.com/opensource/lzo/\n\nthere are 3 sources to the LZO code:\n\n- minilzo (on above site)\n- lzo version 2 (ditto)\n- lzo version 1 (http://sourceforge.net/project/showfiles.php?group_id=102072&package_id=110218&release_id=221836)\n\n### Source Code\n\n```cpp\n// some of the includes are for compression only (not listed here)\n\nint lzo::lzo1x_decompress_safe (const byte* in, byte* out, unsigned OutLen)\n\n// returns length of consumed input bytes, or negative status\n// Outlen is the desired output 'block size' this function will return neg status if the output buffer is not completely filled\n\n// example call\n\nbyte Array = (byte)malloc(Outlen); // no zero clearing is necessary\nint status_or_len = lzo->lzo1x_decompress_safe (input, Array, OutLen);#include \"minilzo.h\"\n\n#include <limits.h>\n#include <stddef.h>\n#include <limits.h>\n#include <stddef.h>\n#include <string.h>\n#include <malloc.h>\n\n#define assert(val)        if (!(val)) return LZO_E_ERROR\n#define M2_MAX_OFFSET    0x0800\n\n#define NEED_OP(x)    if ((unsigned)(op_end - op) < (unsigned)(x)) return LZO_E_OUTPUT_OVERRUN;\n#define TEST_LB()    if (m_pos < out || m_pos >= op) return LZO_E_LOOKBEHIND_OVERRUN;\n\n#define COPY4(dst, src) * (unsigned *)(dst) = * (const unsigned *)(src)\n\nint lzo::lzo1x_decompress_safe (const byte* in, byte* out, unsigned OutLen)\n{\n    register byte* op;\n    register const byte* ip;\n    register size_t t;\n    register const byte* m_pos;\n\n    byte* const op_end = out + OutLen;\n\n    OutLen = 0;\n    op = out;\n    ip = in;\n\n    if (*ip > 17)\n    {\n        t = *ip++ - 17;\n        if (t < 4) goto match_next;\n        assert(t > 0);// return LZO_E_ERROR;\n        NEED_OP(t);\n        do *op++ = *ip++; while (--t > 0);\n        goto first_literal_run;\n    }\n\n    while (1)\n    {\n        t = *ip++;\n        if (t >= 16) goto match;\n        if (t == 0)\n        {\n            while (*ip == 0)\n            {\n                t += 255;\n                ip++;\n            }\n            t += 15 + *ip++;\n        }\n        assert(t > 0); NEED_OP(t+3);\n\n        COPY4(op, ip);\n        op += 4; ip += 4;\n        if (--t > 0)\n        {\n            if (t >= 4)\n            {\n                do {\n                    COPY4(op, ip);\n                    op += 4; ip += 4; t -= 4;\n                } while (t >= 4);\n                if (t > 0) do *op++ = *ip++; while (--t > 0);\n            }\n            else\n                do *op++ = *ip++; while (--t > 0);\n        }\n\nfirst_literal_run:\n\n        t = *ip++;\n        if (t >= 16) goto match;\n\n        m_pos = op - (1 + M2_MAX_OFFSET);\n        m_pos -= t >> 2;\n        m_pos -= *ip++ << 2;\n\n        TEST_LB();\n        NEED_OP(3);\n        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;\n\n        goto match_done;\n\n        do {\nmatch:\n            if (t >= 64)\n            {\n\n                m_pos = op - 1;\n                m_pos -= (t >> 2) & 7;\n                m_pos -= *ip++ << 3;\n                t = (t >> 5) - 1;\n                TEST_LB(); assert(t > 0); NEED_OP(t+3-1);\n                goto copy_match;\n            }\n            else if (t >= 32)\n            {\n                t &= 31;\n                if (t == 0)\n                {\n                    while (*ip == 0)\n                    {\n                        t += 255;\n                        ip++;\n                    }\n                    t += 31 + *ip++;\n                }\n\n                m_pos = op - 1;\n                m_pos -= (ip[0] >> 2) + (ip[1] << 6);\n\n                ip += 2;\n            }\n            else if (t >= 16)\n            {\n\n                m_pos = op;\n                m_pos -= (t & 8) << 11;\n\n                t &= 7;\n                if (t == 0)\n                {\n                    while (*ip == 0)\n                    {\n                        t += 255;\n                        ip++;\n                    }\n                    t += 7 + *ip++;\n                }\n\n                m_pos -= (ip[0] >> 2) + (ip[1] << 6);\n\n                ip += 2;\n                ////// done\n                if (m_pos == op)\n                {\n                    assert(t == 1);\n                    if (m_pos != op_end)\n                        return LZO_E_LOOKBEHIND_UNDERRUN;\n                    return ip-in;\n                }\n                m_pos -= 0x4000;\n            }\n            else\n            {\n                m_pos = op - 1;\n                m_pos -= t >> 2;\n                m_pos -= *ip++ << 2;\n\n                TEST_LB();\n                NEED_OP(2);\n                *op++ = *m_pos++; *op++ = *m_pos;\n                goto match_done;\n            }\n\n            TEST_LB();\n            assert(t > 0);\n            NEED_OP(t+3-1);\n\n            if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)\n            {\n                COPY4(op, m_pos);\n                op += 4; m_pos += 4; t -= 4 - (3 - 1);\n                do {\n                    COPY4(op, m_pos);\n                    op += 4; m_pos += 4; t -= 4;\n                } while (t >= 4);\n                if (t > 0) do *op++ = *m_pos++; while (--t > 0);\n            }\n            else\n            {\ncopy_match:\n                *op++ = *m_pos++; *op++ = *m_pos++;\n\n                do *op++ = *m_pos++; while (--t > 0);\n            }\n\nmatch_done:\n            t = ip[-2] & 3;\n            if (t == 0) break;\n\nmatch_next:\n            assert(t > 0); assert(t < 4); NEED_OP(t);\n            *op++ = *ip++;\n            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }\n\n            t = *ip++;\n        } while (1);\n    }\n\n    // return LZO_E_EOF_NOT_FOUND; // never gets here\n}\n```\n\n### See Also\n\n- Model File Formats","sections":[{"heading":null,"level":1,"markdown":"> **Disclaimer: This page describes internal undocumented structures of Bohemia Interactive software.**\n>\n> This page contains unofficial information.\n>\n> Some usage of this information may constitute a violation of the rights of Bohemia Interactive and is in no way endorsed or recommended by Bohemia Interactive.\n> Bohemia Interactive is not willing to tolerate use of such tools if it contravenes any general licenses granted to end users of this community wiki or BI products.\n\nThis is LZO as defined by oberhumer - http://www.oberhumer.com/opensource/lzo/\n\nthere are 3 sources to the LZO code:\n\n- minilzo (on above site)\n- lzo version 2 (ditto)\n- lzo version 1 (http://sourceforge.net/project/showfiles.php?group_id=102072&package_id=110218&release_id=221836)"},{"heading":"Source Code","level":3,"markdown":"```cpp\n// some of the includes are for compression only (not listed here)\n\nint lzo::lzo1x_decompress_safe (const byte* in, byte* out, unsigned OutLen)\n\n// returns length of consumed input bytes, or negative status\n// Outlen is the desired output 'block size' this function will return neg status if the output buffer is not completely filled\n\n// example call\n\nbyte Array = (byte)malloc(Outlen); // no zero clearing is necessary\nint status_or_len = lzo->lzo1x_decompress_safe (input, Array, OutLen);#include \"minilzo.h\"\n\n#include <limits.h>\n#include <stddef.h>\n#include <limits.h>\n#include <stddef.h>\n#include <string.h>\n#include <malloc.h>\n\n#define assert(val)        if (!(val)) return LZO_E_ERROR\n#define M2_MAX_OFFSET    0x0800\n\n#define NEED_OP(x)    if ((unsigned)(op_end - op) < (unsigned)(x)) return LZO_E_OUTPUT_OVERRUN;\n#define TEST_LB()    if (m_pos < out || m_pos >= op) return LZO_E_LOOKBEHIND_OVERRUN;\n\n#define COPY4(dst, src) * (unsigned *)(dst) = * (const unsigned *)(src)\n\nint lzo::lzo1x_decompress_safe (const byte* in, byte* out, unsigned OutLen)\n{\n    register byte* op;\n    register const byte* ip;\n    register size_t t;\n    register const byte* m_pos;\n\n    byte* const op_end = out + OutLen;\n\n    OutLen = 0;\n    op = out;\n    ip = in;\n\n    if (*ip > 17)\n    {\n        t = *ip++ - 17;\n        if (t < 4) goto match_next;\n        assert(t > 0);// return LZO_E_ERROR;\n        NEED_OP(t);\n        do *op++ = *ip++; while (--t > 0);\n        goto first_literal_run;\n    }\n\n    while (1)\n    {\n        t = *ip++;\n        if (t >= 16) goto match;\n        if (t == 0)\n        {\n            while (*ip == 0)\n            {\n                t += 255;\n                ip++;\n            }\n            t += 15 + *ip++;\n        }\n        assert(t > 0); NEED_OP(t+3);\n\n        COPY4(op, ip);\n        op += 4; ip += 4;\n        if (--t > 0)\n        {\n            if (t >= 4)\n            {\n                do {\n                    COPY4(op, ip);\n                    op += 4; ip += 4; t -= 4;\n                } while (t >= 4);\n                if (t > 0) do *op++ = *ip++; while (--t > 0);\n            }\n            else\n                do *op++ = *ip++; while (--t > 0);\n        }\n\nfirst_literal_run:\n\n        t = *ip++;\n        if (t >= 16) goto match;\n\n        m_pos = op - (1 + M2_MAX_OFFSET);\n        m_pos -= t >> 2;\n        m_pos -= *ip++ << 2;\n\n        TEST_LB();\n        NEED_OP(3);\n        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;\n\n        goto match_done;\n\n        do {\nmatch:\n            if (t >= 64)\n            {\n\n                m_pos = op - 1;\n                m_pos -= (t >> 2) & 7;\n                m_pos -= *ip++ << 3;\n                t = (t >> 5) - 1;\n                TEST_LB(); assert(t > 0); NEED_OP(t+3-1);\n                goto copy_match;\n            }\n            else if (t >= 32)\n            {\n                t &= 31;\n                if (t == 0)\n                {\n                    while (*ip == 0)\n                    {\n                        t += 255;\n                        ip++;\n                    }\n                    t += 31 + *ip++;\n                }\n\n                m_pos = op - 1;\n                m_pos -= (ip[0] >> 2) + (ip[1] << 6);\n\n                ip += 2;\n            }\n            else if (t >= 16)\n            {\n\n                m_pos = op;\n                m_pos -= (t & 8) << 11;\n\n                t &= 7;\n                if (t == 0)\n                {\n                    while (*ip == 0)\n                    {\n                        t += 255;\n                        ip++;\n                    }\n                    t += 7 + *ip++;\n                }\n\n                m_pos -= (ip[0] >> 2) + (ip[1] << 6);\n\n                ip += 2;\n                ////// done\n                if (m_pos == op)\n                {\n                    assert(t == 1);\n                    if (m_pos != op_end)\n                        return LZO_E_LOOKBEHIND_UNDERRUN;\n                    return ip-in;\n                }\n                m_pos -= 0x4000;\n            }\n            else\n            {\n                m_pos = op - 1;\n                m_pos -= t >> 2;\n                m_pos -= *ip++ << 2;\n\n                TEST_LB();\n                NEED_OP(2);\n                *op++ = *m_pos++; *op++ = *m_pos;\n                goto match_done;\n            }\n\n            TEST_LB();\n            assert(t > 0);\n            NEED_OP(t+3-1);\n\n            if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)\n            {\n                COPY4(op, m_pos);\n                op += 4; m_pos += 4; t -= 4 - (3 - 1);\n                do {\n                    COPY4(op, m_pos);\n                    op += 4; m_pos += 4; t -= 4;\n                } while (t >= 4);\n                if (t > 0) do *op++ = *m_pos++; while (--t > 0);\n            }\n            else\n            {\ncopy_match:\n                *op++ = *m_pos++; *op++ = *m_pos++;\n\n                do *op++ = *m_pos++; while (--t > 0);\n            }\n\nmatch_done:\n            t = ip[-2] & 3;\n            if (t == 0) break;\n\nmatch_next:\n            assert(t > 0); assert(t < 4); NEED_OP(t);\n            *op++ = *ip++;\n            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }\n\n            t = *ip++;\n        } while (1);\n    }\n\n    // return LZO_E_EOF_NOT_FOUND; // never gets here\n}\n```"},{"heading":"See Also","level":3,"markdown":"- Model File Formats"}],"categories":["ArmA: Armed Assault: File Formats","Real Virtuality File Formats"],"groups":["Tools and File Formats"]}