Compressed LZO File Format: Difference between revisions
Jump to navigation
Jump to search
Lou Montana (talk | contribs) m (Some wiki formatting) |
Lou Montana (talk | contribs) m (Text replacement - "y[ _]*\|[ _]*(arma[0-9]+)[ _]*\|[ _]+" to "y|$1|") |
||
(2 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{ | {{Feature|UnsupportedDoc}} | ||
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/ | ||
Line 226: | Line 226: | ||
[[Category:BIS File Formats]] | [[Category:BIS File Formats]] | ||
{{GameCategory|arma1|File Formats}} |
Latest revision as of 13:11, 22 June 2021
This is LZO as defined by oberhumer - http://www.oberhumer.com/opensource/lzo/
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)
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
}