ys2-intro/loader/tools/exomizer-3.1/src/output.c

180 lines
4.6 KiB
C
Raw Normal View History

2025-11-13 11:07:39 -05:00
/*
* Copyright (c) 2002 - 2007 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, alter it and re-
* distribute it freely for any non-commercial, non-profit purpose 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.
*
*/
#include <stdlib.h>
#include "log.h"
#include "output.h"
static void bitbuf_bit(struct output_ctx *ctx, int bit)
{
if (ctx->flags_proto & PFLAG_BITS_ORDER_BE)
{
/* ror (new) */
ctx->bitbuf >>= 1;
if (bit)
{
ctx->bitbuf |= 0x80;
}
if (++ctx->bitcount == 8)
{
output_bits_flush(ctx, 0);
}
}
else
{
/* rol (old) */
ctx->bitbuf <<= 1;
if (bit)
{
ctx->bitbuf |= 0x01;
}
if (++ctx->bitcount == 8)
{
output_bits_flush(ctx, 0);
}
}
}
void output_ctx_init(struct output_ctx *ctx, /* IN/OUT */
int flags_proto, /* IN */
struct buf *out)/* IN/OUT */
{
ctx->bitbuf = 0;
ctx->bitcount = 0;
ctx->pos = buf_size(out);
ctx->buf = out;
ctx->flags_proto = flags_proto;
}
unsigned int output_get_pos(struct output_ctx *ctx) /* IN */
{
return ctx->pos;
}
void output_byte(struct output_ctx *ctx, /* IN/OUT */
unsigned char byte) /* IN */
{
/*LOG(LOG_DUMP, ("output_byte: $%02X\n", byte)); */
if(ctx->pos < buf_size(ctx->buf))
{
char *p;
p = buf_data(ctx->buf);
p[ctx->pos] = byte;
}
else
{
while(ctx->pos > buf_size(ctx->buf))
{
buf_append_char(ctx->buf, '\0');
}
buf_append_char(ctx->buf, byte);
}
++(ctx->pos);
}
void output_word(struct output_ctx *ctx, /* IN/OUT */
unsigned short int word) /* IN */
{
output_byte(ctx, (unsigned char) (word & 0xff));
output_byte(ctx, (unsigned char) (word >> 8));
}
void output_bits_flush(struct output_ctx *ctx, /* IN/OUT */
int add_marker_bit) /* IN */
{
if (add_marker_bit)
{
if (ctx->flags_proto & PFLAG_BITS_ORDER_BE)
{
ctx->bitbuf |= (0x80 >> ctx->bitcount);
}
else
{
ctx->bitbuf |= (0x01 << ctx->bitcount);
}
++ctx->bitcount;
}
if (ctx->bitcount > 0)
{
/* flush the bitbuf */
output_byte(ctx, ctx->bitbuf);
LOG(LOG_DUMP, ("bitstream flushed 0x%02X\n", ctx->bitbuf));
/* reset it */
ctx->bitbuf = 0;
ctx->bitcount = 0;
}
}
int output_bits_alignment(struct output_ctx *ctx)
{
int alignment = (8 - ctx->bitcount) & 7;
LOG(LOG_DUMP, ("bitbuf 0x%02X aligned %d\n", ctx->bitbuf, alignment));
return alignment;
}
static void output_bits_int(struct output_ctx *ctx, /* IN/OUT */
int count, /* IN */
int val) /* IN */
{
if (ctx->flags_proto & PFLAG_BITS_COPY_GT_7)
{
while (count > 7)
{
/* at least 8 bits or more are left */
output_byte(ctx, (unsigned char)(val & 0xFF));
count -= 8;
val >>= 8;
}
}
while (count-- > 0)
{
bitbuf_bit(ctx, val & 1);
val >>= 1;
}
}
void output_bits(struct output_ctx *ctx, /* IN/OUT */
int count, /* IN */
int val) /* IN */
{
LOG(LOG_DUMP, ("output bits: count = %d, val = %d\n", count, val));
output_bits_int(ctx, count, val);
}
void output_gamma_code(struct output_ctx *ctx, /* IN/OUT */
int code) /* IN */
{
LOG(LOG_DUMP, ("output gamma: code = %d\n", code));
output_bits_int(ctx, 1, 1);
while (code-- > 0)
{
output_bits_int(ctx, 1, 0);
}
}