Compressed LZO File Format: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
mNo edit summary
m (Text replacement - "y[ _]*\|[ _]*(arma[0-9]+)[ _]*\|[ _]+" to "y|$1|")
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{unsupported-doc}}
{{Feature|UnsupportedDoc}}
===LZO===
This is LZO as defined by oberhumer - http://www.oberhumer.com/opensource/lzo/
This is LZO as defined by oberhumer


http://www.oberhumer.com/opensource/lzo/
there are 3 sources to the LZO code:


there are 3 sources to the lzo code
* minilzo (on above site)
* lzo version 2 (ditto)
* lzo version 1 (http://sourceforge.net/project/showfiles.php?group_id=102072&package_id=110218&release_id=221836)


minilzo (on above site)
lzo version 2 (ditto)
lzo version 1 http://sourceforge.net/project/showfiles.php?group_id=102072&package_id=110218&release_id=221836


<pre><nowiki>
== Source Code ==


<syntaxhighlight lang="cpp">
// some of the includes are for compression only (not listed here)
// some of the includes are for compression only (not listed here)


int lzo::lzo1x_decompress_safe ( const byte* in , byte* out, unsigned OutLen)
int lzo::lzo1x_decompress_safe (const byte* in, byte* out, unsigned OutLen)


// returns length of consumed input bytes ,or, negative status
// returns length of consumed input bytes, or negative status
// Outlen is the desired output 'block size' this function will return neg status if the output buffer is not completely filled
// Outlen is the desired output 'block size' this function will return neg status if the output buffer is not completely filled


// example call
// example call


byte Array=(byte)malloc(Outlen); // no zero clearing is necessary
byte Array = (byte)malloc(Outlen); // no zero clearing is necessary
int status_or_len=lzo->lzo1x_decompress_safe (input, Array,OutLen);#include "minilzo.h"  
int status_or_len = lzo->lzo1x_decompress_safe (input, Array, OutLen);#include "minilzo.h"


#include <limits.h>
#include <limits.h>
Line 32: Line 31:
#include <malloc.h>
#include <malloc.h>


#define assert(val) if (!(val)) return LZO_E_ERROR
#define assert(val) if (!(val)) return LZO_E_ERROR
#define M2_MAX_OFFSET   0x0800
#define M2_MAX_OFFSET 0x0800


#define NEED_OP(x) if ((unsigned)(op_end - op) < (unsigned)(x)) return LZO_E_OUTPUT_OVERRUN;
#define NEED_OP(x) if ((unsigned)(op_end - op) < (unsigned)(x)) return LZO_E_OUTPUT_OVERRUN;
#define TEST_LB()   if (m_pos < out || m_pos >= op) return LZO_E_LOOKBEHIND_OVERRUN;
#define TEST_LB() if (m_pos < out || m_pos >= op) return LZO_E_LOOKBEHIND_OVERRUN;


#define COPY4(dst,src)   * (unsigned *)(dst) = * (const unsigned *)(src)
#define COPY4(dst, src) * (unsigned *)(dst) = * (const unsigned *)(src)


int lzo::lzo1x_decompress_safe ( const byte* in , byte* out, unsigned OutLen)
int lzo::lzo1x_decompress_safe (const byte* in, byte* out, unsigned OutLen)
{
{
register byte* op;
register byte* op;
register const byte* ip;
register const byte* ip;
register size_t t;
register size_t t;
register const byte* m_pos;
register const byte* m_pos;


byte* const op_end = out + OutLen;
byte* const op_end = out + OutLen;


    OutLen = 0;
OutLen = 0;
    op = out;
op = out;
    ip = in;
ip = in;


    if (*ip > 17)
if (*ip > 17)
    {
{
        t = *ip++ - 17;
t = *ip++ - 17;
        if (t < 4) goto match_next;
if (t < 4) goto match_next;
        assert(t > 0);// return LZO_E_ERROR;
assert(t > 0);// return LZO_E_ERROR;
        NEED_OP(t);  
NEED_OP(t);
        do *op++ = *ip++; while (--t > 0);
do *op++ = *ip++; while (--t > 0);
        goto first_literal_run;
goto first_literal_run;
    }
}


    while (1 )
while (1)
    {
{
        t = *ip++;
t = *ip++;
        if (t >= 16)           goto match;
if (t >= 16) goto match;
        if (t == 0)
if (t == 0)
        {
{
            while (*ip == 0)
while (*ip == 0)
            {
{
                t += 255;
t += 255;
                ip++;
ip++;
            }
}
            t += 15 + *ip++;
t += 15 + *ip++;
        }
}
        assert(t > 0); NEED_OP(t+3);  
assert(t > 0); NEED_OP(t+3);


        COPY4(op,ip);
COPY4(op, ip);
        op += 4; ip += 4;
op += 4; ip += 4;
        if (--t > 0)
if (--t > 0)
        {
{
            if (t >= 4)
if (t >= 4)
            {
{
                do {
do {
                    COPY4(op,ip);
COPY4(op, ip);
                    op += 4; ip += 4; t -= 4;
op += 4; ip += 4; t -= 4;
                } while (t >= 4);
} while (t >= 4);
                if (t > 0) do *op++ = *ip++; while (--t > 0);
if (t > 0) do *op++ = *ip++; while (--t > 0);
            }
}
            else
else
                do *op++ = *ip++; while (--t > 0);
do *op++ = *ip++; while (--t > 0);
        }
}


first_literal_run:
first_literal_run:


        t = *ip++;
t = *ip++;
        if (t >= 16) goto match;
if (t >= 16) goto match;


        m_pos = op - (1 + M2_MAX_OFFSET);
m_pos = op - (1 + M2_MAX_OFFSET);
        m_pos -= t >> 2;
m_pos -= t >> 2;
        m_pos -= *ip++ << 2;
m_pos -= *ip++ << 2;


        TEST_LB();  
TEST_LB();
        NEED_OP(3);
NEED_OP(3);
        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
*op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;


        goto match_done;
goto match_done;


        do {
do {
match:
match:
            if (t >= 64)
if (t >= 64)
            {
{


                m_pos = op - 1;
m_pos = op - 1;
                m_pos -= (t >> 2) & 7;
m_pos -= (t >> 2) & 7;
                m_pos -= *ip++ << 3;
m_pos -= *ip++ << 3;
                t = (t >> 5) - 1;
t = (t >> 5) - 1;
                TEST_LB();     assert(t > 0); NEED_OP(t+3-1);
TEST_LB(); assert(t > 0); NEED_OP(t+3-1);
                goto copy_match;
goto copy_match;
            }
}
            else if (t >= 32)
else if (t >= 32)
            {
{
                t &= 31;
t &= 31;
                if (t == 0)
if (t == 0)
                {
{
                    while (*ip == 0)
while (*ip == 0)
                    {
{
                        t += 255;
t += 255;
                        ip++;
ip++;
                    }
}
                    t += 31 + *ip++;
t += 31 + *ip++;
                }
}


                m_pos = op - 1;
m_pos = op - 1;
                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
m_pos -= (ip[0] >> 2) + (ip[1] << 6);


                ip += 2;
ip += 2;
            }
}
            else if (t >= 16)
else if (t >= 16)
            {
{


                m_pos = op;
m_pos = op;
                m_pos -= (t & 8) << 11;
m_pos -= (t & 8) << 11;


                t &= 7;
t &= 7;
                if (t == 0)
if (t == 0)
                {
{
                    while (*ip == 0)
while (*ip == 0)
                    {
{
                        t += 255;
t += 255;
                        ip++;
ip++;
                    }
}
                    t += 7 + *ip++;
t += 7 + *ip++;
                }
}


                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
m_pos -= (ip[0] >> 2) + (ip[1] << 6);


                ip += 2;
ip += 2;
                ////// done
////// done
                if (m_pos == op)
if (m_pos == op)
                {
{
                    assert(t==1);
assert(t == 1);
                    if (m_pos!=op_end)  
if (m_pos != op_end)
                        return LZO_E_LOOKBEHIND_UNDERRUN;
return LZO_E_LOOKBEHIND_UNDERRUN;
                    return ip-in;
return ip-in;
                }
}
                m_pos -= 0x4000;
m_pos -= 0x4000;
            }
}
            else
else
            {
{
                m_pos = op - 1;
m_pos = op - 1;
                m_pos -= t >> 2;
m_pos -= t >> 2;
                m_pos -= *ip++ << 2;
m_pos -= *ip++ << 2;


                TEST_LB();  
TEST_LB();
                NEED_OP(2);
NEED_OP(2);
                *op++ = *m_pos++; *op++ = *m_pos;
*op++ = *m_pos++; *op++ = *m_pos;
                goto match_done;
goto match_done;
            }
}


            TEST_LB();  
TEST_LB();
            assert(t > 0);
assert(t > 0);
            NEED_OP(t+3-1);
NEED_OP(t+3-1);


            if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
            {
{
                COPY4(op,m_pos);
COPY4(op, m_pos);
                op += 4; m_pos += 4; t -= 4 - (3 - 1);
op += 4; m_pos += 4; t -= 4 - (3 - 1);
                do {
do {
                    COPY4(op,m_pos);
COPY4(op, m_pos);
                    op += 4; m_pos += 4; t -= 4;
op += 4; m_pos += 4; t -= 4;
                } while (t >= 4);
} while (t >= 4);
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
if (t > 0) do *op++ = *m_pos++; while (--t > 0);
            }
}
            else
else
            {
{
copy_match:
copy_match:
              *op++ = *m_pos++; *op++ = *m_pos++;
*op++ = *m_pos++; *op++ = *m_pos++;


                do *op++ = *m_pos++; while (--t > 0);
do *op++ = *m_pos++; while (--t > 0);
}


            }
match_done:
match_done:
t = ip[-2] & 3;
if (t == 0) break;


            t = ip[-2] & 3;
            if (t == 0)  break;
match_next:
match_next:
            assert(t > 0); assert(t < 4); NEED_OP(t);  
assert(t > 0); assert(t < 4); NEED_OP(t);
            *op++ = *ip++;
*op++ = *ip++;
            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }


            t = *ip++;
t = *ip++;
        } while (1 );
} while (1);
    }
}
//    return LZO_E_EOF_NOT_FOUND;/never gets here


// return LZO_E_EOF_NOT_FOUND; // never gets here
}
</syntaxhighlight>


}


== See Also ==


</nowiki></pre>
* [[BIS File Formats#3D Model File Formats|Model File Formats]]


=Related Page(s)=


[[BIS_File_Formats#3D_Model_File_Formats|Model File Formats]]
[[Category:BIS File Formats]]
[[Category:BIS_File_Formats]]
{{GameCategory|arma1|File Formats}}
[[Category:ArmA: File Formats]]

Latest revision as of 13:11, 22 June 2021

bi symbol white.png
Disclaimer: This page describes internal undocumented structures of Bohemia Interactive software.

This page contains unofficial information.

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.
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.

This is LZO as defined by oberhumer - http://www.oberhumer.com/opensource/lzo/

there are 3 sources to the LZO code:


Source Code

// some of the includes are for compression only (not listed here)

int lzo::lzo1x_decompress_safe (const byte* in, byte* out, unsigned OutLen)

// returns length of consumed input bytes, or negative status
// Outlen is the desired output 'block size' this function will return neg status if the output buffer is not completely filled

// example call

byte Array = (byte)malloc(Outlen); // no zero clearing is necessary
int status_or_len = lzo->lzo1x_decompress_safe (input, Array, OutLen);#include "minilzo.h"

#include <limits.h>
#include <stddef.h>
#include <limits.h>
#include <stddef.h>
#include <string.h>
#include <malloc.h>

#define assert(val)		if (!(val)) return LZO_E_ERROR
#define M2_MAX_OFFSET	0x0800

#define NEED_OP(x)	if ((unsigned)(op_end - op) < (unsigned)(x)) return LZO_E_OUTPUT_OVERRUN;
#define TEST_LB()	if (m_pos < out || m_pos >= op) return LZO_E_LOOKBEHIND_OVERRUN;

#define COPY4(dst, src) * (unsigned *)(dst) = * (const unsigned *)(src)

int lzo::lzo1x_decompress_safe (const byte* in, byte* out, unsigned OutLen)
{
	register byte* op;
	register const byte* ip;
	register size_t t;
	register const byte* m_pos;

	byte* const op_end = out + OutLen;

	OutLen = 0;
	op = out;
	ip = in;

	if (*ip > 17)
	{
		t = *ip++ - 17;
		if (t < 4) goto match_next;
		assert(t > 0);// return LZO_E_ERROR;
		NEED_OP(t);
		do *op++ = *ip++; while (--t > 0);
		goto first_literal_run;
	}

	while (1)
	{
		t = *ip++;
		if (t >= 16) goto match;
		if (t == 0)
		{
			while (*ip == 0)
			{
				t += 255;
				ip++;
			}
			t += 15 + *ip++;
		}
		assert(t > 0); NEED_OP(t+3);

		COPY4(op, ip);
		op += 4; ip += 4;
		if (--t > 0)
		{
			if (t >= 4)
			{
				do {
					COPY4(op, ip);
					op += 4; ip += 4; t -= 4;
				} while (t >= 4);
				if (t > 0) do *op++ = *ip++; while (--t > 0);
			}
			else
				do *op++ = *ip++; while (--t > 0);
		}

first_literal_run:

		t = *ip++;
		if (t >= 16) goto match;

		m_pos = op - (1 + M2_MAX_OFFSET);
		m_pos -= t >> 2;
		m_pos -= *ip++ << 2;

		TEST_LB();
		NEED_OP(3);
		*op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;

		goto match_done;

		do {
match:
			if (t >= 64)
			{

				m_pos = op - 1;
				m_pos -= (t >> 2) & 7;
				m_pos -= *ip++ << 3;
				t = (t >> 5) - 1;
				TEST_LB(); assert(t > 0); NEED_OP(t+3-1);
				goto copy_match;
			}
			else if (t >= 32)
			{
				t &= 31;
				if (t == 0)
				{
					while (*ip == 0)
					{
						t += 255;
						ip++;
					}
					t += 31 + *ip++;
				}

				m_pos = op - 1;
				m_pos -= (ip[0] >> 2) + (ip[1] << 6);

				ip += 2;
			}
			else if (t >= 16)
			{

				m_pos = op;
				m_pos -= (t & 8) << 11;

				t &= 7;
				if (t == 0)
				{
					while (*ip == 0)
					{
						t += 255;
						ip++;
					}
					t += 7 + *ip++;
				}

				m_pos -= (ip[0] >> 2) + (ip[1] << 6);

				ip += 2;
				////// done
				if (m_pos == op)
				{
					assert(t == 1);
					if (m_pos != op_end)
						return LZO_E_LOOKBEHIND_UNDERRUN;
					return ip-in;
				}
				m_pos -= 0x4000;
			}
			else
			{
				m_pos = op - 1;
				m_pos -= t >> 2;
				m_pos -= *ip++ << 2;

				TEST_LB();
				NEED_OP(2);
				*op++ = *m_pos++; *op++ = *m_pos;
				goto match_done;
			}

			TEST_LB();
			assert(t > 0);
			NEED_OP(t+3-1);

			if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
			{
				COPY4(op, m_pos);
				op += 4; m_pos += 4; t -= 4 - (3 - 1);
				do {
					COPY4(op, m_pos);
					op += 4; m_pos += 4; t -= 4;
				} while (t >= 4);
				if (t > 0) do *op++ = *m_pos++; while (--t > 0);
			}
			else
			{
copy_match:
				*op++ = *m_pos++; *op++ = *m_pos++;

				do *op++ = *m_pos++; while (--t > 0);
			}

match_done:
			t = ip[-2] & 3;
			if (t == 0) break;

match_next:
			assert(t > 0); assert(t < 4); NEED_OP(t);
			*op++ = *ip++;
			if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }

			t = *ip++;
		} while (1);
	}

	// return LZO_E_EOF_NOT_FOUND; // never gets here
}


See Also