ys2-intro/loader/tools/exomizer-3.1/rawdecrs/exodecr.c
2025-11-13 19:07:39 +03:00

190 lines
4.4 KiB
C

/*
* Copyright (c) 2005-2017 Magnus Lind.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented * you must not
* claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any distribution.
*
* 4. The names of this software and/or it's copyright holders may not be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*/
/**
* This decompressor decompresses files that have been compressed
* using the raw sub-sub command with the -b (not default) and -P39
* (default) setting of the raw command.
*/
#include "exodecr.h"
static unsigned short int base[52];
static char bits[52];
static unsigned char bit_buffer;
static int bitbuffer_rotate(int carry)
{
int carry_out;
/* rol */
carry_out = (bit_buffer & 0x80) != 0;
bit_buffer <<= 1;
if (carry)
{
bit_buffer |= 0x01;
}
return carry_out;
}
static unsigned char read_byte(const char **inp)
{
unsigned char val = *--(*inp) & 0xff;
return val;
}
static unsigned short int
read_bits(const char **inp, int bit_count)
{
unsigned short int bits = 0;
int byte_copy = bit_count & 8;
bit_count &= 7;
while(bit_count-- > 0)
{
int carry = bitbuffer_rotate(0);
if (bit_buffer == 0)
{
bit_buffer = read_byte(inp);
carry = bitbuffer_rotate(1);
}
bits <<= 1;
bits |= carry;
}
if (byte_copy != 0)
{
bits <<= 8;
bits |= read_byte(inp);
}
return bits;
}
static void
init_table(const char **inp)
{
int i;
unsigned short int b2;
for(i = 0; i < 52; ++i)
{
unsigned short int b1;
if((i & 15) == 0)
{
b2 = 1;
}
base[i] = b2;
b1 = read_bits(inp, 3);
b1 |= read_bits(inp, 1) << 3;
bits[i] = b1;
b2 += 1 << b1;
}
}
char *
exo_decrunch(const char *in, char *out)
{
unsigned short int index;
unsigned short int length;
unsigned short int offset;
char c;
char literal = 1;
char reuse_offset_state = 1;
bit_buffer = read_byte(&in);
init_table(&in);
goto implicit_literal_byte;
for(;;)
{
literal = read_bits(&in, 1);
if(literal == 1)
{
implicit_literal_byte:
/* literal byte */
length = 1;
goto copy;
}
index = 0;
while(read_bits(&in, 1) == 0)
{
++index;
}
if(index == 16)
{
break;
}
if(index == 17)
{
literal = 1;
length = read_byte(&in) << 8;
length |= read_byte(&in);
goto copy;
}
length = base[index];
length += read_bits(&in, bits[index]);
if ((reuse_offset_state & 3) != 1 || !read_bits(&in, 1))
{
switch(length)
{
case 1:
index = read_bits(&in, 2);
index += 48;
break;
case 2:
index = read_bits(&in, 4);
index += 32;
break;
default:
index = read_bits(&in, 4);
index += 16;
break;
}
offset = base[index];
offset += read_bits(&in, bits[index]);
}
copy:
do
{
--out;
if(literal)
{
c = read_byte(&in);
}
else
{
c = out[offset];
}
*out = c;
}
while(--length > 0);
reuse_offset_state = (reuse_offset_state << 1) | literal;
}
return out;
}