mirror of
https://github.com/aaru-dps/Aaru.Compression.Native.git
synced 2026-07-08 18:06:12 +00:00
Add ACE decompression support for v1 and v2 formats
- Implemented ace_decompress_v2 and ace_decompress_v20_block functions for handling ACE v2 (blocked) decompression. - Added ace_decompress_lz77 function for ACE v1 (LZ77) decompression. - Updated library.h to declare new decompression functions. - Created unit tests for ACE v1 and v2 decompression, validating output against expected CRC32 checksums. - Included necessary binary test data for ACE v1 and v2 formats. - Refactored library.c to improve include order and reduce redundancy in function definitions.
This commit is contained in:
@@ -161,7 +161,17 @@ add_library("Aaru.Compression.Native" SHARED library.c apple_rle.c apple_rle.h a
|
||||
lha/lh_old.c
|
||||
lha/lh_old.h
|
||||
lha/pmarc1.c
|
||||
lha/pmarc1.h)
|
||||
lha/pmarc1.h
|
||||
ace/ace.c
|
||||
ace/ace.h
|
||||
ace/ace_internal.h
|
||||
ace/bitstream.c
|
||||
ace/huffman.c
|
||||
ace/lz77.c
|
||||
ace/sound.c
|
||||
ace/pic.c
|
||||
ace/v1.c
|
||||
ace/v2.c)
|
||||
|
||||
include(3rdparty/bzip2.cmake)
|
||||
include(3rdparty/flac.cmake)
|
||||
|
||||
93
ace/ace.c
Normal file
93
ace/ace.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ace.h"
|
||||
#include "ace_internal.h"
|
||||
|
||||
void ace_init_bitwidth(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
int i, k, j;
|
||||
|
||||
i = k = 0;
|
||||
j = 1;
|
||||
|
||||
do
|
||||
{
|
||||
if(i == j)
|
||||
{
|
||||
k++;
|
||||
j <<= 1;
|
||||
}
|
||||
ctx->bit_width_array[i++] = (uint8_t)k;
|
||||
} while(i < ACE_MAX_DIST2);
|
||||
|
||||
for(i = -128; i <= 127; i++)
|
||||
{
|
||||
if(i < 0)
|
||||
ctx->dif_bit_width_array[(uint8_t)i] = ctx->bit_width_array[-2 * i - 1];
|
||||
else
|
||||
ctx->dif_bit_width_array[(uint8_t)i] = ctx->bit_width_array[2 * i];
|
||||
}
|
||||
}
|
||||
|
||||
int ace_get_bit_width(ace_decompress_ctx_t *ctx, int value)
|
||||
{
|
||||
return value < ACE_MAX_DIST2 ? ctx->bit_width_array[value]
|
||||
: ctx->bit_width_array[value >> ACE_MAX_DIC_BITS2] + ACE_MAX_DIC_BITS2;
|
||||
}
|
||||
|
||||
int ace_decompress_init(ace_decompress_ctx_t *ctx, int dic_bits)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
if(dic_bits < 10) dic_bits = 10;
|
||||
if(dic_bits > ACE_MAX_DIC_BITS) dic_bits = ACE_MAX_DIC_BITS;
|
||||
|
||||
ctx->dic_bits = dic_bits;
|
||||
ctx->dic_size = 1u << dic_bits;
|
||||
ctx->dic_and = ctx->dic_size - 1;
|
||||
|
||||
ctx->dictionary = (uint8_t *)malloc(ctx->dic_size);
|
||||
if(!ctx->dictionary) return -1;
|
||||
memset(ctx->dictionary, 0, ctx->dic_size);
|
||||
|
||||
ace_init_bitwidth(ctx);
|
||||
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i <= 128; i++)
|
||||
{
|
||||
ctx->sound_quantizer[256 - i] = ctx->sound_quantizer[i] = ace_get_bit_width(ctx, i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ace_decompress_free(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
if(ctx->dictionary)
|
||||
{
|
||||
free(ctx->dictionary);
|
||||
ctx->dictionary = NULL;
|
||||
}
|
||||
ace_pic_done(ctx);
|
||||
}
|
||||
245
ace/ace.h
Normal file
245
ace/ace.h
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AARU_ACE_H
|
||||
#define AARU_ACE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* ACE compression technique types */
|
||||
#define ACE_TECHNIQUE_STORE 0
|
||||
#define ACE_TECHNIQUE_LZ77 1 /* ACE v1 LZ77 */
|
||||
#define ACE_TECHNIQUE_BLOCKED 2 /* ACE v2 blocked */
|
||||
|
||||
/* ACE v2 block subtypes */
|
||||
#define ACE_BLOCK_LZ77_NORM 0
|
||||
#define ACE_BLOCK_LZ77_DELTA 1
|
||||
#define ACE_BLOCK_LZ77_EXE 2
|
||||
#define ACE_BLOCK_SOUND_8 3
|
||||
#define ACE_BLOCK_SOUND_16 4
|
||||
#define ACE_BLOCK_SOUND_32_1 5
|
||||
#define ACE_BLOCK_SOUND_32_2 6
|
||||
#define ACE_BLOCK_PIC 7
|
||||
|
||||
/* Constants */
|
||||
#define ACE_MAX_DIC_BITS 22
|
||||
#define ACE_MAX_CODE_WIDTH 11
|
||||
#define ACE_MAX_LEN 259
|
||||
#define ACE_MAX_DIST_AT_LEN2 255
|
||||
#define ACE_MAX_DIST_AT_LEN3 8191
|
||||
#define ACE_MAX_DIC_BITS2 (ACE_MAX_DIC_BITS / 2)
|
||||
#define ACE_MAX_DIC_SIZE (1 << ACE_MAX_DIC_BITS)
|
||||
#define ACE_MAX_DIST2 (1 << ACE_MAX_DIC_BITS2)
|
||||
|
||||
#define ACE_MAX_MAIN_CODE (260 + ACE_MAX_DIC_BITS + 2)
|
||||
#define ACE_MAX_LEN_CODE (256 - 1)
|
||||
#define ACE_TYPE_CODE (260 + ACE_MAX_DIC_BITS + 1)
|
||||
|
||||
#define ACE_MAX_SAVE_WIDTH 7
|
||||
#define ACE_MAX_WIDTH_TO_SAVE 15
|
||||
|
||||
/* Sound constants */
|
||||
#define ACE_SOUND_RUNLEN_CODES 32
|
||||
#define ACE_SOUND_MAX_CODE (256 + ACE_SOUND_RUNLEN_CODES + 1)
|
||||
#define ACE_SOUND_MAX_CODE_WIDTH 10
|
||||
#define ACE_SOUND_TYPE_CODE (256 + ACE_SOUND_RUNLEN_CODES)
|
||||
#define ACE_SOUND_MAX_CHANNELS 3
|
||||
#define ACE_SOUND_MAX_MODELS (ACE_SOUND_MAX_CHANNELS * 3)
|
||||
#define ACE_SOUND_CHANNEL_BLOCK 2000
|
||||
#define ACE_SOUND_HISTORY_SIZE 256
|
||||
#define ACE_SOUND_MAX_BLOCK (ACE_SOUND_CHANNEL_BLOCK * ACE_SOUND_MAX_MODELS + 8)
|
||||
|
||||
/* PIC constants */
|
||||
#define ACE_PIC_N0 32
|
||||
#define ACE_PIC_S1 3
|
||||
#define ACE_PIC_S2 12
|
||||
#define ACE_PIC_S3 40
|
||||
#define ACE_PIC_CONTEXT_NUMBER (9 * 9 * 9)
|
||||
|
||||
/* Read buffer size in 32-bit words */
|
||||
#define ACE_READ_BUF_SIZE 8192
|
||||
|
||||
/* Max partition size for symbol batching */
|
||||
#define ACE_MAX_PART_SIZE 1024
|
||||
|
||||
/* Max delta block */
|
||||
#define ACE_MAX_DELTA_BLOCK 65536
|
||||
|
||||
/* Max HUFF code (for sort arrays) */
|
||||
#define ACE_MAX_HUFF_CODE ACE_SOUND_MAX_CODE
|
||||
|
||||
/* PIC quantizer array access macros */
|
||||
#define ACE_PIC_QUANT(ctx, v) ((ctx)->pic_quantizer[(v) + 255])
|
||||
#define ACE_PIC_QUANT_X9(ctx, v) ((ctx)->pic_quantizer_x9[(v) + 255])
|
||||
#define ACE_PIC_QUANT_X9X9(ctx, v) ((ctx)->pic_quantizer_x9x9[(v) + 255])
|
||||
|
||||
/* Sound channel number tables */
|
||||
extern const int ace_sound_channel_num[4][4];
|
||||
extern const int ace_sound_models[4];
|
||||
|
||||
/* PIC context entry */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t error_counters[4];
|
||||
uint8_t predictor_number;
|
||||
uint16_t used_counter;
|
||||
uint16_t average_counter;
|
||||
} ace_pic_context_t;
|
||||
|
||||
/* Main decompressor context */
|
||||
typedef struct
|
||||
{
|
||||
/* Input buffer and position */
|
||||
const uint8_t *in_buf;
|
||||
size_t in_len;
|
||||
size_t in_pos;
|
||||
|
||||
/* Bit reader state */
|
||||
uint32_t read_buf[ACE_READ_BUF_SIZE];
|
||||
int read_buf_pos;
|
||||
int read_code_bit_pos;
|
||||
uint32_t read_code;
|
||||
|
||||
/* Dictionary */
|
||||
uint8_t *dictionary;
|
||||
uint32_t dic_pos;
|
||||
uint32_t dic_size;
|
||||
uint32_t dic_and;
|
||||
int dic_bits;
|
||||
|
||||
/* File decompression state */
|
||||
int64_t file_size;
|
||||
int64_t file_pos;
|
||||
|
||||
/* Huffman tables for LZ77 */
|
||||
uint16_t main_huff_symbols[(1 << ACE_MAX_CODE_WIDTH) + 1];
|
||||
uint16_t main_huff_widths[ACE_MAX_MAIN_CODE + 2];
|
||||
uint16_t len_huff_symbols[(1 << ACE_MAX_CODE_WIDTH) + 1];
|
||||
uint16_t len_huff_widths[ACE_MAX_LEN_CODE + 3];
|
||||
|
||||
/* Symbol batching buffers */
|
||||
uint16_t main_buf[ACE_MAX_PART_SIZE];
|
||||
uint16_t len_buf[ACE_MAX_PART_SIZE];
|
||||
uint32_t dist_buf[ACE_MAX_PART_SIZE];
|
||||
uint32_t main_buf_pos;
|
||||
uint32_t len_dist_buf_pos;
|
||||
|
||||
/* LZ77 state */
|
||||
int old_dists_pos;
|
||||
uint32_t old_dists[4];
|
||||
uint32_t block_size;
|
||||
uint32_t part_size;
|
||||
uint32_t block_byte_count;
|
||||
uint32_t block_buf_size;
|
||||
|
||||
/* V2 blocked state */
|
||||
int type;
|
||||
int next_type;
|
||||
int over_next_type;
|
||||
|
||||
/* Delta preprocessing */
|
||||
int prep_num_kept_bytes;
|
||||
int prep_kept_bytes_pos;
|
||||
uint32_t prep_last_delta;
|
||||
int delta_dist;
|
||||
int next_delta_dist;
|
||||
int delta_len;
|
||||
int next_delta_len;
|
||||
int delta_block_size;
|
||||
int delta_plane_size;
|
||||
int delta_plane;
|
||||
int delta_plane_pos;
|
||||
uint8_t prep_kept_bytes_buf[ACE_MAX_DELTA_BLOCK + ACE_MAX_LEN];
|
||||
|
||||
/* EXE preprocessing */
|
||||
int exe_mode;
|
||||
int next_exe_mode;
|
||||
|
||||
/* Quicksort working arrays */
|
||||
uint16_t sort_elements[ACE_MAX_HUFF_CODE + 2];
|
||||
uint16_t sort_frequencies[(ACE_MAX_HUFF_CODE + 2) * 2];
|
||||
uint16_t save_widths[ACE_MAX_WIDTH_TO_SAVE];
|
||||
|
||||
/* Bitwidth tables */
|
||||
uint8_t bit_width_array[ACE_MAX_DIST2];
|
||||
uint8_t dif_bit_width_array[256];
|
||||
|
||||
/* Sound decompression */
|
||||
uint16_t sound_huff_symbols[ACE_SOUND_MAX_MODELS][(1 << ACE_SOUND_MAX_CODE_WIDTH) + 1];
|
||||
uint16_t sound_huff_widths[ACE_SOUND_MAX_MODELS][ACE_SOUND_MAX_CODE + 2];
|
||||
int sound_quantizer[256];
|
||||
|
||||
struct
|
||||
{
|
||||
int predictor_dif_cnt[ACE_SOUND_MAX_CHANNELS][2];
|
||||
int last_predictor_dif_cnt[ACE_SOUND_MAX_CHANNELS][2];
|
||||
int rar_dif_cnt[ACE_SOUND_MAX_CHANNELS][4];
|
||||
int rar_coefficient[ACE_SOUND_MAX_CHANNELS][4];
|
||||
int rar_dif[ACE_SOUND_MAX_CHANNELS][9];
|
||||
int byte_count[ACE_SOUND_MAX_CHANNELS];
|
||||
int last_byte[ACE_SOUND_MAX_CHANNELS];
|
||||
int last_delta[ACE_SOUND_MAX_CHANNELS];
|
||||
int state[ACE_SOUND_MAX_CHANNELS];
|
||||
int code[ACE_SOUND_MAX_CHANNELS];
|
||||
int adaptive_model_cnt[ACE_SOUND_MAX_CHANNELS];
|
||||
int adaptive_model_use[ACE_SOUND_MAX_CHANNELS];
|
||||
int models;
|
||||
int mode;
|
||||
int sound_block_size;
|
||||
} sound_var;
|
||||
|
||||
/* PIC decompression */
|
||||
int pic_quantizer[511]; /* indexed as [v+255] for v in -255..255 */
|
||||
int pic_quantizer_x9[511];
|
||||
int pic_quantizer_x9x9[511];
|
||||
ace_pic_context_t pic_context[2][ACE_PIC_CONTEXT_NUMBER];
|
||||
ace_pic_context_t *cur_context;
|
||||
int8_t *pic_data[2];
|
||||
int pic_width;
|
||||
int pic_planes;
|
||||
int pic_data_pos;
|
||||
int pic_cur_col;
|
||||
int pic_cur_plane;
|
||||
int pic_cur_pred;
|
||||
int pic_cur_state;
|
||||
int pic_pixel_a;
|
||||
int pic_pixel_b;
|
||||
int pic_pixel_c;
|
||||
int pic_pixel_d;
|
||||
int pic_pixel_x;
|
||||
|
||||
/* Error flag */
|
||||
int error;
|
||||
} ace_decompress_ctx_t;
|
||||
|
||||
/* Initialize context for decompression */
|
||||
int ace_decompress_init(ace_decompress_ctx_t *ctx, int dic_bits);
|
||||
|
||||
/* Decompress an ACE v1 (LZ77) compressed block */
|
||||
int ace_decompress_v1(ace_decompress_ctx_t *ctx, const uint8_t *in_buf, size_t in_len, uint8_t *out_buf,
|
||||
size_t *out_len);
|
||||
|
||||
/* Decompress an ACE v2 (blocked) compressed block */
|
||||
int ace_decompress_v2(ace_decompress_ctx_t *ctx, const uint8_t *in_buf, size_t in_len, uint8_t *out_buf,
|
||||
size_t *out_len);
|
||||
|
||||
/* Free context resources */
|
||||
void ace_decompress_free(ace_decompress_ctx_t *ctx);
|
||||
|
||||
#endif /* AARU_ACE_H */
|
||||
60
ace/ace_internal.h
Normal file
60
ace/ace_internal.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AARU_ACE_INTERNAL_H
|
||||
#define AARU_ACE_INTERNAL_H
|
||||
|
||||
#include "ace.h"
|
||||
|
||||
/* bitstream.c */
|
||||
void ace_fill_read_buf(ace_decompress_ctx_t *ctx);
|
||||
void ace_add_bits(ace_decompress_ctx_t *ctx, int bits);
|
||||
void ace_init_read_buf(ace_decompress_ctx_t *ctx);
|
||||
|
||||
/* huffman.c */
|
||||
int ace_make_codes(ace_decompress_ctx_t *ctx, unsigned max_width, unsigned tab_size, uint16_t *widths, uint16_t *codes);
|
||||
int ace_read_widths(ace_decompress_ctx_t *ctx, unsigned max_width, uint16_t *codes, uint16_t *widths,
|
||||
unsigned max_size);
|
||||
|
||||
/* lz77.c */
|
||||
void ace_lz77_write_char(ace_decompress_ctx_t *ctx, uint8_t ch);
|
||||
void ace_lz77_copy_string(ace_decompress_ctx_t *ctx, uint32_t dist, int len);
|
||||
int ace_lz77_calc_huff_tabs(ace_decompress_ctx_t *ctx);
|
||||
int ace_lz77_read_symbols(ace_decompress_ctx_t *ctx);
|
||||
void ace_lz77_block_core(ace_decompress_ctx_t *ctx);
|
||||
int ace_lz77_block(ace_decompress_ctx_t *ctx, uint8_t *buf, int len);
|
||||
void ace_lz77_copy_to_dict(ace_decompress_ctx_t *ctx, const uint8_t *buf, int len);
|
||||
|
||||
/* sound.c */
|
||||
int ace_sound_block(ace_decompress_ctx_t *ctx, uint8_t *buf, int len);
|
||||
void ace_sound_init(ace_decompress_ctx_t *ctx, int type);
|
||||
|
||||
/* pic.c */
|
||||
int ace_pic_block(ace_decompress_ctx_t *ctx, uint8_t *buf, int len);
|
||||
void ace_pic_init(ace_decompress_ctx_t *ctx);
|
||||
void ace_pic_done(ace_decompress_ctx_t *ctx);
|
||||
|
||||
/* v2.c */
|
||||
int ace_decompress_v20_block(ace_decompress_ctx_t *ctx, uint8_t *buf, int len);
|
||||
int ace_lz77_preprocess_block(ace_decompress_ctx_t *ctx, uint8_t *buf, int len);
|
||||
|
||||
/* ace.c (init/bitwidth) */
|
||||
void ace_init_bitwidth(ace_decompress_ctx_t *ctx);
|
||||
int ace_get_bit_width(ace_decompress_ctx_t *ctx, int value);
|
||||
|
||||
#endif /* AARU_ACE_INTERNAL_H */
|
||||
108
ace/bitstream.c
Normal file
108
ace/bitstream.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ace.h"
|
||||
#include "ace_internal.h"
|
||||
|
||||
void ace_fill_read_buf(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
uint32_t i;
|
||||
size_t bytes_to_read;
|
||||
size_t words_to_read;
|
||||
|
||||
ctx->read_buf[0] = ctx->read_buf[ACE_READ_BUF_SIZE - 2];
|
||||
ctx->read_buf[1] = ctx->read_buf[ACE_READ_BUF_SIZE - 1];
|
||||
ctx->read_buf_pos -= ACE_READ_BUF_SIZE - 2;
|
||||
|
||||
bytes_to_read = (ACE_READ_BUF_SIZE - 2) * 4;
|
||||
if(bytes_to_read > ctx->in_len - ctx->in_pos) bytes_to_read = ctx->in_len - ctx->in_pos;
|
||||
|
||||
words_to_read = bytes_to_read / 4;
|
||||
|
||||
for(i = 0; i < words_to_read; i++)
|
||||
{
|
||||
size_t off = ctx->in_pos + i * 4;
|
||||
ctx->read_buf[2 + i] = (uint32_t)ctx->in_buf[off] | ((uint32_t)ctx->in_buf[off + 1] << 8) |
|
||||
((uint32_t)ctx->in_buf[off + 2] << 16) | ((uint32_t)ctx->in_buf[off + 3] << 24);
|
||||
}
|
||||
|
||||
if(bytes_to_read > words_to_read * 4)
|
||||
{
|
||||
uint32_t word = 0;
|
||||
size_t off = ctx->in_pos + words_to_read * 4;
|
||||
size_t rem = bytes_to_read - words_to_read * 4;
|
||||
size_t b;
|
||||
for(b = 0; b < rem; b++) word |= (uint32_t)ctx->in_buf[off + b] << (b * 8);
|
||||
ctx->read_buf[2 + words_to_read] = word;
|
||||
}
|
||||
|
||||
ctx->in_pos += bytes_to_read;
|
||||
}
|
||||
|
||||
void ace_add_bits(ace_decompress_ctx_t *ctx, int bits)
|
||||
{
|
||||
uint32_t b0, b1;
|
||||
|
||||
ctx->read_buf_pos += (ctx->read_code_bit_pos += bits) >> 5;
|
||||
ctx->read_code_bit_pos &= 31;
|
||||
|
||||
if(ctx->read_buf_pos == ACE_READ_BUF_SIZE - 2) ace_fill_read_buf(ctx);
|
||||
|
||||
b0 = ctx->read_buf[ctx->read_buf_pos];
|
||||
b1 = ctx->read_buf[ctx->read_buf_pos + 1];
|
||||
|
||||
ctx->read_code = (b0 << ctx->read_code_bit_pos) +
|
||||
((b1 >> (32 - ctx->read_code_bit_pos)) & ((uint32_t)(!ctx->read_code_bit_pos) - 1));
|
||||
}
|
||||
|
||||
void ace_init_read_buf(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
size_t bytes_to_read;
|
||||
size_t words_to_read;
|
||||
size_t i;
|
||||
|
||||
bytes_to_read = ACE_READ_BUF_SIZE * 4;
|
||||
if(bytes_to_read > ctx->in_len - ctx->in_pos) bytes_to_read = ctx->in_len - ctx->in_pos;
|
||||
|
||||
words_to_read = bytes_to_read / 4;
|
||||
|
||||
for(i = 0; i < words_to_read; i++)
|
||||
{
|
||||
size_t off = ctx->in_pos + i * 4;
|
||||
ctx->read_buf[i] = (uint32_t)ctx->in_buf[off] | ((uint32_t)ctx->in_buf[off + 1] << 8) |
|
||||
((uint32_t)ctx->in_buf[off + 2] << 16) | ((uint32_t)ctx->in_buf[off + 3] << 24);
|
||||
}
|
||||
|
||||
if(bytes_to_read > words_to_read * 4)
|
||||
{
|
||||
uint32_t word = 0;
|
||||
size_t off = ctx->in_pos + words_to_read * 4;
|
||||
size_t rem = bytes_to_read - words_to_read * 4;
|
||||
size_t b;
|
||||
for(b = 0; b < rem; b++) word |= (uint32_t)ctx->in_buf[off + b] << (b * 8);
|
||||
ctx->read_buf[words_to_read] = word;
|
||||
}
|
||||
|
||||
ctx->in_pos += bytes_to_read;
|
||||
|
||||
ctx->read_code = ctx->read_buf[0];
|
||||
ctx->read_code_bit_pos = 0;
|
||||
ctx->read_buf_pos = 0;
|
||||
}
|
||||
176
ace/huffman.c
Normal file
176
ace/huffman.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ace.h"
|
||||
#include "ace_internal.h"
|
||||
|
||||
static void ace_qsort_xchg(uint16_t *a, uint16_t *b)
|
||||
{
|
||||
uint16_t tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
static void ace_qsort_range(ace_decompress_ctx_t *ctx, int left, int right)
|
||||
{
|
||||
int new_left, new_right;
|
||||
uint16_t hyphen;
|
||||
|
||||
new_left = left;
|
||||
new_right = right;
|
||||
hyphen = ctx->sort_frequencies[right];
|
||||
|
||||
do
|
||||
{
|
||||
while(ctx->sort_frequencies[new_left] > hyphen) new_left++;
|
||||
while(ctx->sort_frequencies[new_right] < hyphen) new_right--;
|
||||
|
||||
if(new_left <= new_right)
|
||||
{
|
||||
ace_qsort_xchg(&ctx->sort_frequencies[new_left], &ctx->sort_frequencies[new_right]);
|
||||
ace_qsort_xchg(&ctx->sort_elements[new_left], &ctx->sort_elements[new_right]);
|
||||
new_left++;
|
||||
new_right--;
|
||||
}
|
||||
} while(new_left < new_right);
|
||||
|
||||
if(left < new_right)
|
||||
{
|
||||
if(left < new_right - 1)
|
||||
ace_qsort_range(ctx, left, new_right);
|
||||
else if(ctx->sort_frequencies[left] < ctx->sort_frequencies[new_right])
|
||||
{
|
||||
ace_qsort_xchg(&ctx->sort_frequencies[left], &ctx->sort_frequencies[new_right]);
|
||||
ace_qsort_xchg(&ctx->sort_elements[left], &ctx->sort_elements[new_right]);
|
||||
}
|
||||
}
|
||||
|
||||
if(right > new_left)
|
||||
{
|
||||
if(new_left < right - 1)
|
||||
ace_qsort_range(ctx, new_left, right);
|
||||
else if(ctx->sort_frequencies[new_left] < ctx->sort_frequencies[right])
|
||||
{
|
||||
ace_qsort_xchg(&ctx->sort_frequencies[new_left], &ctx->sort_frequencies[right]);
|
||||
ace_qsort_xchg(&ctx->sort_elements[new_left], &ctx->sort_elements[right]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ace_quicksort(ace_decompress_ctx_t *ctx, int n)
|
||||
{
|
||||
int i;
|
||||
for(i = n + 1; i--;) ctx->sort_elements[i] = (uint16_t)i;
|
||||
ace_qsort_range(ctx, 0, n);
|
||||
}
|
||||
|
||||
static void ace_memset16(uint16_t *buf, uint16_t val, int count)
|
||||
{
|
||||
while(count--) *buf++ = val;
|
||||
}
|
||||
|
||||
int ace_make_codes(ace_decompress_ctx_t *ctx, unsigned max_width, unsigned tab_size, uint16_t *widths, uint16_t *codes)
|
||||
{
|
||||
unsigned num_codes, code, code_pos, i, max_code_pos, actual_size;
|
||||
|
||||
memcpy(ctx->sort_frequencies, widths, (tab_size + 1) * sizeof(uint16_t));
|
||||
|
||||
if(tab_size)
|
||||
ace_quicksort(ctx, (int)tab_size);
|
||||
else
|
||||
ctx->sort_elements[0] = 0;
|
||||
|
||||
ctx->sort_frequencies[tab_size + 1] = actual_size = code_pos = 0;
|
||||
|
||||
while(ctx->sort_frequencies[actual_size]) actual_size++;
|
||||
|
||||
if(actual_size < 2)
|
||||
{
|
||||
i = ctx->sort_elements[0];
|
||||
widths[i] = 1;
|
||||
actual_size += (actual_size == 0);
|
||||
}
|
||||
actual_size--;
|
||||
|
||||
max_code_pos = 1u << max_width;
|
||||
for(i = actual_size + 1; i-- && code_pos < max_code_pos;)
|
||||
{
|
||||
num_codes = 1u << (max_width - ctx->sort_frequencies[i]);
|
||||
code = ctx->sort_elements[i];
|
||||
if(code_pos + num_codes > max_code_pos) return 0;
|
||||
ace_memset16(&codes[code_pos], (uint16_t)code, (int)num_codes);
|
||||
code_pos += num_codes;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ace_read_widths(ace_decompress_ctx_t *ctx, unsigned max_width, uint16_t *codes, uint16_t *widths, unsigned max_size)
|
||||
{
|
||||
unsigned code, i, width_pos, num_widths, len, upper_width, lower_width;
|
||||
|
||||
memset(widths, 0, max_size * sizeof(uint16_t));
|
||||
memset(codes, 0, (1u << max_width) * sizeof(uint16_t));
|
||||
|
||||
num_widths = ctx->read_code >> (32 - 9);
|
||||
ace_add_bits(ctx, 9);
|
||||
if(num_widths > max_size) num_widths = max_size;
|
||||
|
||||
lower_width = ctx->read_code >> (32 - 4);
|
||||
ace_add_bits(ctx, 4);
|
||||
upper_width = ctx->read_code >> (32 - 4);
|
||||
ace_add_bits(ctx, 4);
|
||||
|
||||
for(i = 0; i <= upper_width; i++)
|
||||
{
|
||||
ctx->save_widths[i] = ctx->read_code >> (32 - 3);
|
||||
ace_add_bits(ctx, 3);
|
||||
}
|
||||
|
||||
if(!ace_make_codes(ctx, ACE_MAX_SAVE_WIDTH, upper_width, ctx->save_widths, codes)) return 0;
|
||||
|
||||
width_pos = 0;
|
||||
while(width_pos <= num_widths)
|
||||
{
|
||||
code = codes[ctx->read_code >> (32 - ACE_MAX_SAVE_WIDTH)];
|
||||
ace_add_bits(ctx, ctx->save_widths[code]);
|
||||
|
||||
if(code < upper_width)
|
||||
widths[width_pos++] = (uint16_t)code;
|
||||
else
|
||||
{
|
||||
len = (ctx->read_code >> 28) + 4;
|
||||
ace_add_bits(ctx, 4);
|
||||
while(len-- && width_pos <= num_widths) widths[width_pos++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(upper_width)
|
||||
{
|
||||
for(i = 1; i <= num_widths; i++) widths[i] = (widths[i] + widths[i - 1]) % upper_width;
|
||||
}
|
||||
|
||||
for(i = 0; i <= num_widths; i++)
|
||||
{
|
||||
if(widths[i]) widths[i] += (uint16_t)lower_width;
|
||||
}
|
||||
|
||||
return ace_make_codes(ctx, max_width, num_widths, widths, codes);
|
||||
}
|
||||
260
ace/lz77.c
Normal file
260
ace/lz77.c
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ace.h"
|
||||
#include "ace_internal.h"
|
||||
|
||||
void ace_lz77_write_char(ace_decompress_ctx_t *ctx, uint8_t ch)
|
||||
{
|
||||
ctx->dictionary[ctx->dic_pos] = ch;
|
||||
ctx->dic_pos = (ctx->dic_pos + 1) & ctx->dic_and;
|
||||
ctx->block_byte_count++;
|
||||
}
|
||||
|
||||
void ace_lz77_copy_string(ace_decompress_ctx_t *ctx, uint32_t dist, int len)
|
||||
{
|
||||
uint32_t src_pos;
|
||||
int i;
|
||||
|
||||
src_pos = (ctx->dic_pos - dist) & ctx->dic_and;
|
||||
|
||||
if(src_pos >= ctx->dic_size - ACE_MAX_LEN || ctx->dic_pos >= ctx->dic_size - ACE_MAX_LEN)
|
||||
{
|
||||
for(i = len; i--;)
|
||||
{
|
||||
ctx->dictionary[ctx->dic_pos] = ctx->dictionary[src_pos];
|
||||
ctx->dic_pos = (ctx->dic_pos + 1) & ctx->dic_and;
|
||||
src_pos = (src_pos + 1) & ctx->dic_and;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0; i < len; i++) ctx->dictionary[ctx->dic_pos + i] = ctx->dictionary[src_pos + i];
|
||||
ctx->dic_pos = (ctx->dic_pos + len) & ctx->dic_and;
|
||||
}
|
||||
|
||||
ctx->block_byte_count += len;
|
||||
}
|
||||
|
||||
int ace_lz77_calc_huff_tabs(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
if(!ace_read_widths(ctx, ACE_MAX_CODE_WIDTH, ctx->main_huff_symbols, ctx->main_huff_widths, ACE_MAX_MAIN_CODE) ||
|
||||
!ace_read_widths(ctx, ACE_MAX_CODE_WIDTH, ctx->len_huff_symbols, ctx->len_huff_widths, ACE_MAX_LEN_CODE))
|
||||
return 0;
|
||||
|
||||
ctx->block_size = ctx->read_code >> (32 - 15);
|
||||
ace_add_bits(ctx, 15);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ace_lz77_read_symbols(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
int symbol_count, match_count, symbol, type;
|
||||
|
||||
if(!ctx->block_size && !ace_lz77_calc_huff_tabs(ctx)) return 0;
|
||||
|
||||
ctx->part_size = ACE_MAX_PART_SIZE > ctx->block_size ? ctx->block_size : ACE_MAX_PART_SIZE;
|
||||
ctx->block_size -= ctx->part_size;
|
||||
|
||||
match_count = 0;
|
||||
|
||||
for(symbol_count = 0; (uint32_t)symbol_count < ctx->part_size; symbol_count++)
|
||||
{
|
||||
symbol = ctx->main_huff_symbols[ctx->read_code >> (32 - ACE_MAX_CODE_WIDTH)];
|
||||
ace_add_bits(ctx, ctx->main_huff_widths[symbol]);
|
||||
ctx->main_buf[symbol_count] = (uint16_t)symbol;
|
||||
|
||||
if(symbol > 255)
|
||||
{
|
||||
if(symbol == ACE_TYPE_CODE)
|
||||
{
|
||||
type = ctx->read_code >> 24;
|
||||
ctx->len_buf[match_count] = (uint16_t)type;
|
||||
ace_add_bits(ctx, 8);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ACE_BLOCK_LZ77_DELTA:
|
||||
ctx->dist_buf[match_count] = ctx->read_code >> (32 - 25);
|
||||
ace_add_bits(ctx, 25);
|
||||
break;
|
||||
case ACE_BLOCK_LZ77_EXE:
|
||||
ctx->dist_buf[match_count] = ctx->read_code >> (32 - 8);
|
||||
ace_add_bits(ctx, 8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
match_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(symbol > 259)
|
||||
{
|
||||
if((symbol -= 260) > 1)
|
||||
{
|
||||
ctx->dist_buf[match_count] = (ctx->read_code >> (33 - symbol)) + (1u << (symbol - 1));
|
||||
ace_add_bits(ctx, symbol - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->dist_buf[match_count] = (uint32_t)symbol;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->len_buf[match_count] = ctx->len_huff_symbols[ctx->read_code >> (32 - ACE_MAX_CODE_WIDTH)];
|
||||
ace_add_bits(ctx, ctx->len_huff_widths[ctx->len_buf[match_count]]);
|
||||
match_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->len_dist_buf_pos = ctx->main_buf_pos = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ace_lz77_block_core(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
int symbol, len_symbol, i;
|
||||
uint32_t match_dist;
|
||||
|
||||
while(ctx->block_byte_count < ctx->block_buf_size)
|
||||
{
|
||||
if(ctx->main_buf_pos == ctx->part_size)
|
||||
{
|
||||
if(!ace_lz77_read_symbols(ctx)) return;
|
||||
}
|
||||
|
||||
symbol = ctx->main_buf[ctx->main_buf_pos++];
|
||||
|
||||
if(symbol > 255)
|
||||
{
|
||||
if(symbol == ACE_TYPE_CODE)
|
||||
{
|
||||
ctx->next_type = ctx->len_buf[ctx->len_dist_buf_pos] & 255;
|
||||
|
||||
switch(ctx->next_type)
|
||||
{
|
||||
case ACE_BLOCK_LZ77_DELTA:
|
||||
ctx->next_delta_dist = ctx->dist_buf[ctx->len_dist_buf_pos] >> 17;
|
||||
ctx->next_delta_len = ctx->dist_buf[ctx->len_dist_buf_pos] & 0x1FFFF;
|
||||
break;
|
||||
case ACE_BLOCK_LZ77_EXE:
|
||||
ctx->next_exe_mode = ctx->dist_buf[ctx->len_dist_buf_pos];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->len_dist_buf_pos++;
|
||||
break;
|
||||
}
|
||||
|
||||
if(symbol > 259)
|
||||
{
|
||||
symbol -= 260;
|
||||
match_dist = ctx->dist_buf[ctx->len_dist_buf_pos];
|
||||
|
||||
ctx->old_dists_pos = (ctx->old_dists_pos + 1) & 3;
|
||||
ctx->old_dists[ctx->old_dists_pos] = match_dist;
|
||||
|
||||
i = 2;
|
||||
if(match_dist > ACE_MAX_DIST_AT_LEN2)
|
||||
{
|
||||
i++;
|
||||
if(match_dist > ACE_MAX_DIST_AT_LEN3) i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
match_dist = ctx->old_dists[(ctx->old_dists_pos - (symbol &= 255)) & 3];
|
||||
|
||||
for(i = symbol; i >= 0; i--)
|
||||
ctx->old_dists[(ctx->old_dists_pos - i) & 3] = ctx->old_dists[(ctx->old_dists_pos - i + 1) & 3];
|
||||
|
||||
ctx->old_dists[ctx->old_dists_pos] = match_dist;
|
||||
i = symbol > 1 ? 3 : 2;
|
||||
}
|
||||
|
||||
len_symbol = ctx->len_buf[ctx->len_dist_buf_pos++] + i;
|
||||
match_dist++;
|
||||
ace_lz77_copy_string(ctx, match_dist, len_symbol);
|
||||
}
|
||||
else
|
||||
{
|
||||
ace_lz77_write_char(ctx, (uint8_t)symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ace_lz77_block(ace_decompress_ctx_t *ctx, uint8_t *buf, int len)
|
||||
{
|
||||
int old_pos, i;
|
||||
|
||||
old_pos = ctx->dic_pos;
|
||||
ctx->block_byte_count = 0;
|
||||
|
||||
if(len < ACE_MAX_LEN)
|
||||
{
|
||||
if(ctx->file_size <= 0 || (int64_t)len < ctx->file_size) return 0;
|
||||
ctx->block_buf_size = (uint32_t)ctx->file_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->block_buf_size = len - ACE_MAX_LEN;
|
||||
}
|
||||
|
||||
if((int64_t)ctx->block_buf_size > ctx->file_size) ctx->block_buf_size = (uint32_t)ctx->file_size;
|
||||
if(ctx->block_buf_size > ctx->dic_size - ACE_MAX_LEN) ctx->block_buf_size = ctx->dic_size - ACE_MAX_LEN;
|
||||
|
||||
if(ctx->file_size > 0 && ctx->block_buf_size)
|
||||
{
|
||||
ace_lz77_block_core(ctx);
|
||||
|
||||
if(ctx->block_byte_count <= (uint32_t)len)
|
||||
{
|
||||
if((uint32_t)old_pos + ctx->block_byte_count > ctx->dic_size)
|
||||
{
|
||||
i = ctx->dic_size - old_pos;
|
||||
memcpy(buf, &ctx->dictionary[old_pos], i);
|
||||
memcpy(&buf[i], ctx->dictionary, ctx->block_byte_count - i);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(buf, &ctx->dictionary[old_pos], ctx->block_byte_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->file_size -= ctx->block_byte_count;
|
||||
return (int)ctx->block_byte_count;
|
||||
}
|
||||
|
||||
void ace_lz77_copy_to_dict(ace_decompress_ctx_t *ctx, const uint8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
ctx->dictionary[ctx->dic_pos] = buf[i];
|
||||
ctx->dic_pos = (ctx->dic_pos + 1) & ctx->dic_and;
|
||||
}
|
||||
}
|
||||
378
ace/pic.c
Normal file
378
ace/pic.c
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ace.h"
|
||||
#include "ace_internal.h"
|
||||
|
||||
static int ace_pic_golomb_rice(ace_decompress_ctx_t *ctx, int k)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
err = k ? (int)(ctx->read_code >> (32 - k)) : 0;
|
||||
ace_add_bits(ctx, k);
|
||||
|
||||
do
|
||||
{
|
||||
i = ctx->read_code >> 31;
|
||||
if(i) err += 1 << k;
|
||||
ace_add_bits(ctx, 1);
|
||||
} while(i);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ace_pic_get_context(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
return ACE_PIC_QUANT_X9X9(ctx, ctx->pic_pixel_d - ctx->pic_pixel_a) +
|
||||
ACE_PIC_QUANT_X9(ctx, ctx->pic_pixel_a - ctx->pic_pixel_c) +
|
||||
ACE_PIC_QUANT(ctx, ctx->pic_pixel_c - ctx->pic_pixel_b);
|
||||
}
|
||||
|
||||
static void ace_pic_init_model(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
int pred, i;
|
||||
for(pred = 0; pred <= 1; pred++)
|
||||
{
|
||||
memset(&ctx->pic_context[pred], 0, sizeof(ctx->pic_context[0]));
|
||||
for(i = 0; i < ACE_PIC_CONTEXT_NUMBER; i++) ctx->pic_context[pred][i].average_counter = 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void ace_pic_init_quantizers(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
int i;
|
||||
for(i = -255; i <= 255; i++)
|
||||
{
|
||||
if(i <= -ACE_PIC_S3)
|
||||
ACE_PIC_QUANT(ctx, i) = -4;
|
||||
else if(i <= -ACE_PIC_S2)
|
||||
ACE_PIC_QUANT(ctx, i) = -3;
|
||||
else if(i <= -ACE_PIC_S1)
|
||||
ACE_PIC_QUANT(ctx, i) = -2;
|
||||
else if(i <= -1)
|
||||
ACE_PIC_QUANT(ctx, i) = -1;
|
||||
else if(!i)
|
||||
ACE_PIC_QUANT(ctx, i) = 0;
|
||||
else if(i < ACE_PIC_S1)
|
||||
ACE_PIC_QUANT(ctx, i) = 1;
|
||||
else if(i < ACE_PIC_S2)
|
||||
ACE_PIC_QUANT(ctx, i) = 2;
|
||||
else if(i < ACE_PIC_S3)
|
||||
ACE_PIC_QUANT(ctx, i) = 3;
|
||||
else
|
||||
ACE_PIC_QUANT(ctx, i) = 4;
|
||||
}
|
||||
|
||||
for(i = -255; i <= 255; i++) ACE_PIC_QUANT_X9(ctx, i) = 9 * ACE_PIC_QUANT(ctx, i);
|
||||
for(i = -255; i <= 255; i++) ACE_PIC_QUANT_X9X9(ctx, i) = 9 * ACE_PIC_QUANT_X9(ctx, i);
|
||||
}
|
||||
|
||||
static void ace_pic_set_pixels1(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
ctx->pic_pixel_d = ctx->pic_data[1][ctx->pic_cur_plane];
|
||||
ctx->pic_pixel_a = ctx->pic_pixel_b = ctx->pic_pixel_c = ctx->pic_pixel_x = 0;
|
||||
|
||||
if(ctx->pic_cur_pred == 1)
|
||||
{
|
||||
ctx->pic_pixel_a = ctx->pic_pixel_b = ctx->pic_pixel_c = ctx->pic_pixel_x = 128;
|
||||
if(ctx->pic_cur_plane > 0) ctx->pic_pixel_d -= ctx->pic_data[1][ctx->pic_cur_plane - 1] - 128;
|
||||
}
|
||||
else if(ctx->pic_cur_pred == 2)
|
||||
{
|
||||
ctx->pic_pixel_a = ctx->pic_pixel_b = ctx->pic_pixel_c = ctx->pic_pixel_x = 128;
|
||||
if(ctx->pic_cur_plane > 0) ctx->pic_pixel_d -= (ctx->pic_data[1][ctx->pic_cur_plane - 1] * 11 >> 4) - 128;
|
||||
}
|
||||
}
|
||||
|
||||
static void ace_pic_set_pixels2(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
ctx->pic_pixel_c = ctx->pic_pixel_a;
|
||||
ctx->pic_pixel_a = ctx->pic_pixel_d;
|
||||
ctx->pic_pixel_b = ctx->pic_pixel_x;
|
||||
}
|
||||
|
||||
static void ace_pic_set_pixels3(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
ctx->pic_pixel_a = ctx->pic_data[1][ctx->pic_cur_col];
|
||||
ctx->pic_pixel_b = ctx->pic_data[0][ctx->pic_cur_col - ctx->pic_planes];
|
||||
ctx->pic_pixel_c = ctx->pic_data[1][ctx->pic_cur_col - ctx->pic_planes];
|
||||
|
||||
if(ctx->pic_cur_pred == 1)
|
||||
{
|
||||
ctx->pic_pixel_a -= ctx->pic_data[1][ctx->pic_cur_col - 1] - 128;
|
||||
ctx->pic_pixel_b -= ctx->pic_data[0][ctx->pic_cur_col - ctx->pic_planes - 1] - 128;
|
||||
ctx->pic_pixel_c -= ctx->pic_data[1][ctx->pic_cur_col - ctx->pic_planes - 1] - 128;
|
||||
}
|
||||
else if(ctx->pic_cur_pred == 2)
|
||||
{
|
||||
ctx->pic_pixel_a -= (ctx->pic_data[1][ctx->pic_cur_col - 1] * 11 >> 4) - 128;
|
||||
ctx->pic_pixel_b -= (ctx->pic_data[0][ctx->pic_cur_col - ctx->pic_planes - 1] * 11 >> 4) - 128;
|
||||
ctx->pic_pixel_c -= (ctx->pic_data[1][ctx->pic_cur_col - ctx->pic_planes - 1] * 11 >> 4) - 128;
|
||||
}
|
||||
}
|
||||
|
||||
static void ace_pic_set_pixel_state(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
ctx->pic_pixel_d = ctx->pic_data[1][ctx->pic_cur_col + ctx->pic_planes];
|
||||
|
||||
if(ctx->pic_cur_pred == 1)
|
||||
ctx->pic_pixel_d -= ctx->pic_data[1][ctx->pic_cur_col + ctx->pic_planes - 1] - 128;
|
||||
else if(ctx->pic_cur_pred == 2)
|
||||
ctx->pic_pixel_d -= (ctx->pic_data[1][ctx->pic_cur_col + ctx->pic_planes - 1] * 11 >> 4) - 128;
|
||||
|
||||
ctx->pic_cur_state = abs(ace_pic_get_context(ctx));
|
||||
}
|
||||
|
||||
static void ace_pic_pixel(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
int k, best_predictor, best_error_count;
|
||||
uint8_t m_epsilon, predicted;
|
||||
int8_t epsilon;
|
||||
|
||||
ctx->cur_context[ctx->pic_cur_state].used_counter++;
|
||||
|
||||
k = ctx->bit_width_array[ctx->cur_context[ctx->pic_cur_state].average_counter /
|
||||
ctx->cur_context[ctx->pic_cur_state].used_counter];
|
||||
|
||||
m_epsilon = (uint8_t)ace_pic_golomb_rice(ctx, k);
|
||||
|
||||
if(m_epsilon & 1)
|
||||
epsilon = -(int8_t)(m_epsilon / 2) - 1;
|
||||
else
|
||||
epsilon = (int8_t)(m_epsilon / 2);
|
||||
|
||||
switch(ctx->cur_context[ctx->pic_cur_state].predictor_number)
|
||||
{
|
||||
case 0:
|
||||
predicted = (uint8_t)ctx->pic_pixel_a;
|
||||
break;
|
||||
case 1:
|
||||
predicted = (uint8_t)ctx->pic_pixel_b;
|
||||
break;
|
||||
case 2:
|
||||
predicted = (uint8_t)((ctx->pic_pixel_a + ctx->pic_pixel_b) >> 1);
|
||||
break;
|
||||
case 3:
|
||||
predicted = (uint8_t)(ctx->pic_pixel_a + ctx->pic_pixel_b - ctx->pic_pixel_c);
|
||||
break;
|
||||
default:
|
||||
predicted = 0;
|
||||
}
|
||||
|
||||
ctx->pic_pixel_x = (uint8_t)(epsilon + predicted);
|
||||
|
||||
ctx->cur_context[ctx->pic_cur_state].error_counters[0] +=
|
||||
ctx->dif_bit_width_array[(uint8_t)(ctx->pic_pixel_x - ctx->pic_pixel_a)];
|
||||
|
||||
best_predictor = 0;
|
||||
best_error_count = ctx->cur_context[ctx->pic_cur_state].error_counters[0];
|
||||
|
||||
ctx->cur_context[ctx->pic_cur_state].error_counters[1] +=
|
||||
ctx->dif_bit_width_array[(uint8_t)(ctx->pic_pixel_x - ctx->pic_pixel_b)];
|
||||
|
||||
if(ctx->cur_context[ctx->pic_cur_state].error_counters[1] < best_error_count)
|
||||
{
|
||||
best_predictor = 1;
|
||||
best_error_count = ctx->cur_context[ctx->pic_cur_state].error_counters[1];
|
||||
}
|
||||
|
||||
ctx->cur_context[ctx->pic_cur_state].error_counters[2] +=
|
||||
ctx->dif_bit_width_array[(uint8_t)(ctx->pic_pixel_x - ((ctx->pic_pixel_a + ctx->pic_pixel_b) >> 1))];
|
||||
|
||||
if(ctx->cur_context[ctx->pic_cur_state].error_counters[2] < best_error_count)
|
||||
{
|
||||
best_predictor = 2;
|
||||
best_error_count = ctx->cur_context[ctx->pic_cur_state].error_counters[2];
|
||||
}
|
||||
|
||||
ctx->cur_context[ctx->pic_cur_state].error_counters[3] += ctx->dif_bit_width_array[(
|
||||
uint8_t)(ctx->pic_pixel_x - (ctx->pic_pixel_a + ctx->pic_pixel_b - ctx->pic_pixel_c))];
|
||||
|
||||
if(ctx->cur_context[ctx->pic_cur_state].error_counters[3] < best_error_count) best_predictor = 3;
|
||||
|
||||
{
|
||||
uint32_t *ec = (uint32_t *)&ctx->cur_context[ctx->pic_cur_state].error_counters;
|
||||
if(*ec & 0x80808080u) *ec = (*ec >> 1) & 0x7f7f7f7fu;
|
||||
}
|
||||
|
||||
ctx->cur_context[ctx->pic_cur_state].predictor_number = (uint8_t)best_predictor;
|
||||
ctx->cur_context[ctx->pic_cur_state].average_counter += (uint16_t)abs(epsilon);
|
||||
|
||||
if(ctx->cur_context[ctx->pic_cur_state].used_counter == ACE_PIC_N0)
|
||||
{
|
||||
ctx->cur_context[ctx->pic_cur_state].used_counter >>= 1;
|
||||
ctx->cur_context[ctx->pic_cur_state].average_counter >>= 1;
|
||||
}
|
||||
|
||||
switch(ctx->pic_cur_pred)
|
||||
{
|
||||
case 0:
|
||||
ctx->pic_data[0][ctx->pic_cur_col] = (int8_t)ctx->pic_pixel_x;
|
||||
break;
|
||||
case 1:
|
||||
ctx->pic_data[0][ctx->pic_cur_col] =
|
||||
(int8_t)(ctx->pic_pixel_x + ctx->pic_data[0][ctx->pic_cur_col - 1] - 128);
|
||||
break;
|
||||
case 2:
|
||||
ctx->pic_data[0][ctx->pic_cur_col] =
|
||||
(int8_t)(ctx->pic_pixel_x + (ctx->pic_data[0][ctx->pic_cur_col - 1] * 11 >> 4) - 128);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ace_pic_symbol(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
ace_pic_set_pixels2(ctx);
|
||||
ace_pic_set_pixels3(ctx);
|
||||
ace_pic_set_pixel_state(ctx);
|
||||
ace_pic_pixel(ctx);
|
||||
}
|
||||
|
||||
static void ace_pic_line(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
int8_t *temp;
|
||||
|
||||
for(ctx->pic_cur_plane = 0; ctx->pic_cur_plane < ctx->pic_planes; ctx->pic_cur_plane++)
|
||||
{
|
||||
if(ctx->pic_cur_plane)
|
||||
{
|
||||
ctx->cur_context = ctx->pic_context[1];
|
||||
ctx->pic_cur_pred = ctx->read_code >> (32 - 2);
|
||||
ace_add_bits(ctx, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->cur_context = ctx->pic_context[0];
|
||||
ctx->pic_cur_pred = 0;
|
||||
}
|
||||
|
||||
ace_pic_set_pixels1(ctx);
|
||||
|
||||
for(ctx->pic_cur_col = ctx->pic_cur_plane; ctx->pic_cur_col < ctx->pic_width;
|
||||
ctx->pic_cur_col += ctx->pic_planes)
|
||||
{
|
||||
ace_pic_symbol(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
ctx->pic_data_pos = ctx->pic_width;
|
||||
temp = ctx->pic_data[0];
|
||||
ctx->pic_data[0] = ctx->pic_data[1];
|
||||
ctx->pic_data[1] = temp;
|
||||
}
|
||||
|
||||
void ace_pic_done(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
if(ctx->pic_data[0])
|
||||
{
|
||||
free(ctx->pic_data[0] - ctx->pic_planes);
|
||||
free(ctx->pic_data[1] - ctx->pic_planes);
|
||||
ctx->pic_data[0] = NULL;
|
||||
ctx->pic_data[1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ace_pic_init(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
int i, j;
|
||||
int8_t *buf;
|
||||
|
||||
ace_pic_done(ctx);
|
||||
|
||||
ctx->pic_width = ace_pic_golomb_rice(ctx, 12);
|
||||
ctx->pic_planes = ace_pic_golomb_rice(ctx, 2);
|
||||
|
||||
i = ctx->pic_width + 2 * ctx->pic_planes;
|
||||
|
||||
for(j = 0; j <= 1; j++)
|
||||
{
|
||||
buf = (int8_t *)malloc(i);
|
||||
if(!buf)
|
||||
{
|
||||
ctx->error = 1;
|
||||
return;
|
||||
}
|
||||
memset(buf, 0, i);
|
||||
ctx->pic_data[j] = buf + ctx->pic_planes;
|
||||
}
|
||||
|
||||
ace_pic_init_model(ctx);
|
||||
ace_pic_init_quantizers(ctx);
|
||||
ctx->pic_data_pos = 0;
|
||||
}
|
||||
|
||||
int ace_pic_block(ace_decompress_ctx_t *ctx, uint8_t *buf, int len)
|
||||
{
|
||||
int i, rest_len;
|
||||
|
||||
rest_len = len;
|
||||
|
||||
while(rest_len)
|
||||
{
|
||||
if(!ctx->pic_data_pos)
|
||||
{
|
||||
if(ctx->file_size)
|
||||
{
|
||||
i = ctx->read_code >> (32 - 1);
|
||||
ace_add_bits(ctx, 1);
|
||||
|
||||
if(!i)
|
||||
{
|
||||
ctx->next_type = ctx->read_code >> (32 - 8);
|
||||
ace_add_bits(ctx, 8);
|
||||
|
||||
switch(ctx->next_type)
|
||||
{
|
||||
case ACE_BLOCK_LZ77_DELTA:
|
||||
ctx->next_delta_dist = ctx->read_code >> (32 - 8);
|
||||
ace_add_bits(ctx, 8);
|
||||
ctx->next_delta_len = ctx->read_code >> (32 - 17);
|
||||
ace_add_bits(ctx, 17);
|
||||
break;
|
||||
case ACE_BLOCK_LZ77_EXE:
|
||||
ctx->next_exe_mode = ctx->read_code >> (32 - 8);
|
||||
ace_add_bits(ctx, 8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ace_pic_line(ctx);
|
||||
}
|
||||
|
||||
i = rest_len > ctx->pic_data_pos ? ctx->pic_data_pos : rest_len;
|
||||
memcpy(buf, &ctx->pic_data[1][ctx->pic_width - ctx->pic_data_pos], i);
|
||||
|
||||
buf += i;
|
||||
rest_len -= i;
|
||||
ctx->pic_data_pos -= i;
|
||||
ctx->file_size -= i;
|
||||
}
|
||||
|
||||
return len - rest_len;
|
||||
}
|
||||
250
ace/sound.c
Normal file
250
ace/sound.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ace.h"
|
||||
#include "ace_internal.h"
|
||||
|
||||
const int ace_sound_channel_num[4][4] = {
|
||||
{0, 0, 0, 0},
|
||||
{0, 1, 0, 1},
|
||||
{0, 1, 2, 0},
|
||||
{0, 1, 2, 0}
|
||||
};
|
||||
|
||||
const int ace_sound_models[4] = {3, 6, 9, 6};
|
||||
|
||||
static uint8_t ace_sound_get_predicted(ace_decompress_ctx_t *ctx, int ch)
|
||||
{
|
||||
return (uint8_t)((8 * ctx->sound_var.last_byte[ch] +
|
||||
ctx->sound_var.rar_coefficient[ch][0] * ctx->sound_var.rar_dif_cnt[ch][0] +
|
||||
ctx->sound_var.rar_coefficient[ch][1] * ctx->sound_var.rar_dif_cnt[ch][1] +
|
||||
ctx->sound_var.rar_coefficient[ch][2] * ctx->sound_var.rar_dif_cnt[ch][2] +
|
||||
ctx->sound_var.rar_coefficient[ch][3] * ctx->sound_var.rar_dif_cnt[ch][3]) >>
|
||||
3);
|
||||
}
|
||||
|
||||
static int ace_sound_calc_tabs(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < ctx->sound_var.models; i++)
|
||||
{
|
||||
ace_read_widths(ctx, ACE_SOUND_MAX_CODE_WIDTH, ctx->sound_huff_symbols[i], ctx->sound_huff_widths[i],
|
||||
ACE_SOUND_MAX_CODE);
|
||||
}
|
||||
ctx->sound_var.sound_block_size = ctx->read_code >> (32 - 15);
|
||||
ace_add_bits(ctx, 15);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ace_sound_get_symbol(ace_decompress_ctx_t *ctx, int model, int channel)
|
||||
{
|
||||
int symbol;
|
||||
|
||||
if(!ctx->sound_var.sound_block_size) ace_sound_calc_tabs(ctx);
|
||||
|
||||
model <<= 1;
|
||||
if(!model) model += ctx->sound_var.adaptive_model_use[channel];
|
||||
model += 3 * channel;
|
||||
|
||||
symbol = ctx->sound_huff_symbols[model][ctx->read_code >> (32 - ACE_SOUND_MAX_CODE_WIDTH)];
|
||||
ace_add_bits(ctx, ctx->sound_huff_widths[model][symbol]);
|
||||
ctx->sound_var.sound_block_size--;
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
static int ace_sound_get(ace_decompress_ctx_t *ctx, int channel)
|
||||
{
|
||||
int err;
|
||||
|
||||
if(ctx->sound_var.state[channel] != 2)
|
||||
{
|
||||
ctx->sound_var.code[channel] = ace_sound_get_symbol(ctx, ctx->sound_var.state[channel], channel);
|
||||
|
||||
if(ctx->sound_var.code[channel] == ACE_SOUND_TYPE_CODE)
|
||||
{
|
||||
ctx->next_type = ctx->read_code >> (32 - 8);
|
||||
ace_add_bits(ctx, 8);
|
||||
|
||||
switch(ctx->next_type)
|
||||
{
|
||||
case ACE_BLOCK_LZ77_DELTA:
|
||||
ctx->next_delta_dist = ctx->read_code >> (32 - 8);
|
||||
ace_add_bits(ctx, 8);
|
||||
ctx->next_delta_len = ctx->read_code >> (32 - 17);
|
||||
ace_add_bits(ctx, 17);
|
||||
break;
|
||||
case ACE_BLOCK_LZ77_EXE:
|
||||
ctx->next_exe_mode = ctx->read_code >> (32 - 8);
|
||||
ace_add_bits(ctx, 8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(ctx->sound_var.state[channel] != 2)
|
||||
{
|
||||
if(!ctx->sound_var.state[channel] && ctx->sound_var.code[channel] < ACE_SOUND_RUNLEN_CODES)
|
||||
{
|
||||
ctx->sound_var.state[channel] = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ctx->sound_var.state[channel] == 1)
|
||||
{
|
||||
err = ctx->sound_var.code[channel];
|
||||
ctx->sound_var.state[channel] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = ctx->sound_var.code[channel] - ACE_SOUND_RUNLEN_CODES;
|
||||
|
||||
ctx->sound_var.adaptive_model_cnt[channel] =
|
||||
(ctx->sound_var.adaptive_model_cnt[channel] * 7 >> 3) + err;
|
||||
|
||||
ctx->sound_var.adaptive_model_use[channel] = ctx->sound_var.adaptive_model_cnt[channel] > 40;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ctx->sound_var.state[channel] == 2)
|
||||
{
|
||||
if(!ctx->sound_var.code[channel])
|
||||
ctx->sound_var.state[channel] = 1;
|
||||
else
|
||||
ctx->sound_var.code[channel]--;
|
||||
|
||||
err = 0;
|
||||
}
|
||||
|
||||
return err & 1 ? (255 - (err >> 1)) : err >> 1;
|
||||
}
|
||||
|
||||
static int ace_sound_rar_predict(ace_decompress_ctx_t *ctx, int channel)
|
||||
{
|
||||
int pch = ace_sound_get_predicted(ctx, channel);
|
||||
|
||||
if(ctx->sound_var.predictor_dif_cnt[channel][0] > ctx->sound_var.predictor_dif_cnt[channel][1])
|
||||
pch = ctx->sound_var.last_byte[channel];
|
||||
|
||||
return pch - 128;
|
||||
}
|
||||
|
||||
static void ace_sound_rar_adjust(ace_decompress_ctx_t *ctx, int channel, int ch)
|
||||
{
|
||||
int pred_dif, i, min_dif, min_dif_pos = 0, pch;
|
||||
|
||||
ctx->sound_var.byte_count[channel]++;
|
||||
|
||||
pch = ace_sound_get_predicted(ctx, channel);
|
||||
pred_dif = ((int8_t)(pch - ch)) << 3;
|
||||
|
||||
ctx->sound_var.rar_dif[channel][0] += abs(pred_dif - ctx->sound_var.rar_dif_cnt[channel][0]);
|
||||
ctx->sound_var.rar_dif[channel][1] += abs(pred_dif + ctx->sound_var.rar_dif_cnt[channel][0]);
|
||||
ctx->sound_var.rar_dif[channel][2] += abs(pred_dif - ctx->sound_var.rar_dif_cnt[channel][1]);
|
||||
ctx->sound_var.rar_dif[channel][3] += abs(pred_dif + ctx->sound_var.rar_dif_cnt[channel][1]);
|
||||
ctx->sound_var.rar_dif[channel][4] += abs(pred_dif - ctx->sound_var.rar_dif_cnt[channel][2]);
|
||||
ctx->sound_var.rar_dif[channel][5] += abs(pred_dif + ctx->sound_var.rar_dif_cnt[channel][2]);
|
||||
ctx->sound_var.rar_dif[channel][6] += abs(pred_dif - ctx->sound_var.rar_dif_cnt[channel][3]);
|
||||
ctx->sound_var.rar_dif[channel][7] += abs(pred_dif + ctx->sound_var.rar_dif_cnt[channel][3]);
|
||||
ctx->sound_var.rar_dif[channel][8] += abs(pred_dif);
|
||||
|
||||
ctx->sound_var.predictor_dif_cnt[channel][0] += ctx->sound_quantizer[(uint8_t)(pred_dif >> 3)];
|
||||
ctx->sound_var.predictor_dif_cnt[channel][1] +=
|
||||
ctx->sound_quantizer[(uint8_t)(ctx->sound_var.last_byte[channel] - ch)];
|
||||
|
||||
ctx->sound_var.last_delta[channel] = (int8_t)(ch - ctx->sound_var.last_byte[channel]);
|
||||
ctx->sound_var.last_byte[channel] = ch;
|
||||
|
||||
if(!(ctx->sound_var.byte_count[channel] & 0x1f))
|
||||
{
|
||||
min_dif = 0xffff;
|
||||
for(i = 8; i >= 0; i--)
|
||||
{
|
||||
if(ctx->sound_var.rar_dif[channel][i] <= min_dif)
|
||||
{
|
||||
min_dif = ctx->sound_var.rar_dif[channel][i];
|
||||
min_dif_pos = i;
|
||||
}
|
||||
ctx->sound_var.rar_dif[channel][i] = 0;
|
||||
}
|
||||
|
||||
if(min_dif_pos != 8)
|
||||
{
|
||||
i = min_dif_pos >> 1;
|
||||
if(!(min_dif_pos & 1))
|
||||
{
|
||||
if(ctx->sound_var.rar_coefficient[channel][i] >= -16) ctx->sound_var.rar_coefficient[channel][i]--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ctx->sound_var.rar_coefficient[channel][i] <= 16) ctx->sound_var.rar_coefficient[channel][i]++;
|
||||
}
|
||||
}
|
||||
|
||||
if(!(ctx->sound_var.byte_count[channel] & 0xff))
|
||||
{
|
||||
ctx->sound_var.predictor_dif_cnt[channel][0] -= ctx->sound_var.last_predictor_dif_cnt[channel][0];
|
||||
ctx->sound_var.last_predictor_dif_cnt[channel][0] = ctx->sound_var.predictor_dif_cnt[channel][0];
|
||||
ctx->sound_var.predictor_dif_cnt[channel][1] -= ctx->sound_var.last_predictor_dif_cnt[channel][1];
|
||||
ctx->sound_var.last_predictor_dif_cnt[channel][1] = ctx->sound_var.predictor_dif_cnt[channel][1];
|
||||
}
|
||||
}
|
||||
|
||||
ctx->sound_var.rar_dif_cnt[channel][3] = ctx->sound_var.rar_dif_cnt[channel][2];
|
||||
ctx->sound_var.rar_dif_cnt[channel][2] = ctx->sound_var.rar_dif_cnt[channel][1];
|
||||
ctx->sound_var.rar_dif_cnt[channel][1] =
|
||||
ctx->sound_var.last_delta[channel] - ctx->sound_var.rar_dif_cnt[channel][0];
|
||||
ctx->sound_var.rar_dif_cnt[channel][0] = ctx->sound_var.last_delta[channel];
|
||||
}
|
||||
|
||||
int ace_sound_block(ace_decompress_ctx_t *ctx, uint8_t *buf, int len)
|
||||
{
|
||||
int i, err, channel, sample;
|
||||
|
||||
len &= (int)0xfffffffc;
|
||||
if(len > (int)ctx->file_size) len = (int)ctx->file_size;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
channel = ace_sound_channel_num[ctx->sound_var.mode][i & 3];
|
||||
err = ace_sound_get(ctx, channel);
|
||||
|
||||
if(err == -1) break;
|
||||
|
||||
sample = (uint8_t)(err + ace_sound_rar_predict(ctx, channel));
|
||||
buf[i] = (uint8_t)(sample + 128);
|
||||
ace_sound_rar_adjust(ctx, channel, buf[i]);
|
||||
}
|
||||
|
||||
ctx->file_size -= i;
|
||||
return i;
|
||||
}
|
||||
|
||||
void ace_sound_init(ace_decompress_ctx_t *ctx, int type)
|
||||
{
|
||||
memset(&ctx->sound_var, 0, sizeof(ctx->sound_var));
|
||||
ctx->sound_var.mode = type - ACE_BLOCK_SOUND_8;
|
||||
ctx->sound_var.models = ace_sound_models[ctx->sound_var.mode];
|
||||
}
|
||||
148
ace/v1.c
Normal file
148
ace/v1.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ace.h"
|
||||
#include "ace_internal.h"
|
||||
|
||||
static void ace_v1_decompress_core(ace_decompress_ctx_t *ctx)
|
||||
{
|
||||
int c, lg, i, k;
|
||||
uint32_t dist;
|
||||
|
||||
while(ctx->block_byte_count < ctx->block_buf_size && !ctx->error)
|
||||
{
|
||||
if(!ctx->block_size)
|
||||
{
|
||||
if(!ace_read_widths(ctx, ACE_MAX_CODE_WIDTH, ctx->main_huff_symbols, ctx->main_huff_widths,
|
||||
ACE_MAX_MAIN_CODE) ||
|
||||
!ace_read_widths(ctx, ACE_MAX_CODE_WIDTH, ctx->len_huff_symbols, ctx->len_huff_widths, ACE_MAX_LEN_CODE))
|
||||
{
|
||||
ctx->error = 1;
|
||||
return;
|
||||
}
|
||||
ctx->block_size = ctx->read_code >> (32 - 15);
|
||||
ace_add_bits(ctx, 15);
|
||||
}
|
||||
|
||||
c = ctx->main_huff_symbols[ctx->read_code >> (32 - ACE_MAX_CODE_WIDTH)];
|
||||
ace_add_bits(ctx, ctx->main_huff_widths[c]);
|
||||
ctx->block_size--;
|
||||
|
||||
if(c > 255)
|
||||
{
|
||||
if(c > 259)
|
||||
{
|
||||
if((c -= 260) > 1)
|
||||
{
|
||||
dist = (ctx->read_code >> (33 - c)) + (1u << (c - 1));
|
||||
ace_add_bits(ctx, c - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
dist = (uint32_t)c;
|
||||
}
|
||||
ctx->old_dists[(ctx->old_dists_pos = (ctx->old_dists_pos + 1) & 3)] = dist;
|
||||
i = 2;
|
||||
if(dist > ACE_MAX_DIST_AT_LEN2)
|
||||
{
|
||||
i++;
|
||||
if(dist > ACE_MAX_DIST_AT_LEN3) i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dist = ctx->old_dists[(ctx->old_dists_pos - (c &= 255)) & 3];
|
||||
for(k = c + 1; k--;)
|
||||
ctx->old_dists[(ctx->old_dists_pos - k) & 3] = ctx->old_dists[(ctx->old_dists_pos - k + 1) & 3];
|
||||
ctx->old_dists[ctx->old_dists_pos] = dist;
|
||||
i = 2;
|
||||
if(c > 1) i++;
|
||||
}
|
||||
|
||||
lg = ctx->len_huff_symbols[ctx->read_code >> (32 - ACE_MAX_CODE_WIDTH)];
|
||||
ace_add_bits(ctx, ctx->len_huff_widths[lg]);
|
||||
lg += i;
|
||||
dist++;
|
||||
ace_lz77_copy_string(ctx, dist, lg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ace_lz77_write_char(ctx, (uint8_t)c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ace_decompress_v1(ace_decompress_ctx_t *ctx, const uint8_t *in_buf, size_t in_len, uint8_t *out_buf,
|
||||
size_t *out_len)
|
||||
{
|
||||
size_t orig_size = *out_len;
|
||||
uint32_t old_pos;
|
||||
int i;
|
||||
|
||||
ctx->in_buf = in_buf;
|
||||
ctx->in_len = in_len;
|
||||
ctx->in_pos = 0;
|
||||
ctx->error = 0;
|
||||
ctx->dic_pos = 0;
|
||||
|
||||
ctx->file_size = (int64_t)orig_size;
|
||||
ctx->block_size = 0;
|
||||
ctx->block_byte_count = 0;
|
||||
ctx->old_dists_pos = 0;
|
||||
memset(ctx->old_dists, 0, sizeof(ctx->old_dists));
|
||||
|
||||
ace_init_read_buf(ctx);
|
||||
|
||||
{
|
||||
size_t total_out = 0;
|
||||
|
||||
while(ctx->file_size > 0 && !ctx->error)
|
||||
{
|
||||
old_pos = ctx->dic_pos;
|
||||
ctx->block_byte_count = 0;
|
||||
ctx->block_buf_size = (uint32_t)ctx->file_size;
|
||||
|
||||
if(ctx->block_buf_size > ctx->dic_size - ACE_MAX_LEN) ctx->block_buf_size = ctx->dic_size - ACE_MAX_LEN;
|
||||
|
||||
ace_v1_decompress_core(ctx);
|
||||
|
||||
if(ctx->block_byte_count > 0 && total_out + ctx->block_byte_count <= orig_size)
|
||||
{
|
||||
if(old_pos + ctx->block_byte_count > ctx->dic_size)
|
||||
{
|
||||
i = ctx->dic_size - old_pos;
|
||||
memcpy(out_buf + total_out, &ctx->dictionary[old_pos], i);
|
||||
memcpy(out_buf + total_out + i, ctx->dictionary, ctx->block_byte_count - i);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(out_buf + total_out, &ctx->dictionary[old_pos], ctx->block_byte_count);
|
||||
}
|
||||
}
|
||||
|
||||
total_out += ctx->block_byte_count;
|
||||
ctx->file_size -= ctx->block_byte_count;
|
||||
}
|
||||
|
||||
*out_len = total_out;
|
||||
}
|
||||
|
||||
return ctx->error ? -1 : 0;
|
||||
}
|
||||
248
ace/v2.c
Normal file
248
ace/v2.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ace.h"
|
||||
#include "ace_internal.h"
|
||||
|
||||
int ace_decompress_v20_block(ace_decompress_ctx_t *ctx, uint8_t *buf, int len)
|
||||
{
|
||||
int r, rest_len;
|
||||
|
||||
rest_len = len;
|
||||
|
||||
do
|
||||
{
|
||||
if(ctx->type != ctx->next_type)
|
||||
{
|
||||
switch(ctx->next_type)
|
||||
{
|
||||
case ACE_BLOCK_SOUND_8:
|
||||
case ACE_BLOCK_SOUND_16:
|
||||
case ACE_BLOCK_SOUND_32_1:
|
||||
case ACE_BLOCK_SOUND_32_2:
|
||||
ace_sound_init(ctx, ctx->next_type);
|
||||
break;
|
||||
case ACE_BLOCK_PIC:
|
||||
ace_pic_init(ctx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->type = ctx->next_type;
|
||||
|
||||
switch(ctx->type)
|
||||
{
|
||||
case ACE_BLOCK_LZ77_NORM:
|
||||
case ACE_BLOCK_LZ77_DELTA:
|
||||
case ACE_BLOCK_LZ77_EXE:
|
||||
r = ace_lz77_preprocess_block(ctx, buf, rest_len);
|
||||
break;
|
||||
case ACE_BLOCK_PIC:
|
||||
r = ace_pic_block(ctx, buf, rest_len);
|
||||
ace_lz77_copy_to_dict(ctx, buf, r);
|
||||
break;
|
||||
case ACE_BLOCK_SOUND_8:
|
||||
case ACE_BLOCK_SOUND_16:
|
||||
case ACE_BLOCK_SOUND_32_1:
|
||||
case ACE_BLOCK_SOUND_32_2:
|
||||
r = ace_sound_block(ctx, buf, rest_len);
|
||||
ace_lz77_copy_to_dict(ctx, buf, r);
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->file_pos += r;
|
||||
buf += r;
|
||||
rest_len -= r;
|
||||
} while((r || ctx->next_type != ctx->type || (ctx->next_type == ACE_BLOCK_LZ77_DELTA && ctx->next_delta_len)) &&
|
||||
(rest_len > ACE_MAX_LEN || (ctx->file_size > 0 && ctx->file_size <= ACE_MAX_LEN && rest_len > 0)));
|
||||
|
||||
return len - rest_len;
|
||||
}
|
||||
|
||||
int ace_lz77_preprocess_block(ace_decompress_ctx_t *ctx, uint8_t *buf, int len)
|
||||
{
|
||||
int i, r, pos, read_count;
|
||||
|
||||
if(ctx->type == ACE_BLOCK_LZ77_DELTA)
|
||||
{
|
||||
if(!ctx->prep_num_kept_bytes)
|
||||
{
|
||||
ctx->delta_dist = ctx->next_delta_dist;
|
||||
ctx->delta_len = ctx->next_delta_len;
|
||||
ctx->next_delta_len = 0;
|
||||
|
||||
do
|
||||
{
|
||||
ctx->prep_num_kept_bytes +=
|
||||
(read_count = ace_lz77_block(ctx, ctx->prep_kept_bytes_buf + ctx->prep_num_kept_bytes,
|
||||
ACE_MAX_DELTA_BLOCK + ACE_MAX_LEN - ctx->prep_num_kept_bytes));
|
||||
} while(ctx->prep_num_kept_bytes < ctx->delta_len);
|
||||
|
||||
ctx->delta_block_size = ctx->prep_num_kept_bytes;
|
||||
|
||||
if(ctx->delta_dist)
|
||||
ctx->delta_plane_size = ctx->delta_block_size / ctx->delta_dist;
|
||||
else
|
||||
ctx->delta_plane_size = 0;
|
||||
|
||||
ctx->over_next_type = ctx->next_type;
|
||||
ctx->next_type = ACE_BLOCK_LZ77_DELTA;
|
||||
|
||||
for(i = 0; i < ctx->delta_block_size; i++)
|
||||
ctx->prep_last_delta = (ctx->prep_kept_bytes_buf[i] += (uint8_t)ctx->prep_last_delta);
|
||||
|
||||
ctx->prep_kept_bytes_pos = ctx->delta_plane = ctx->delta_plane_pos = 0;
|
||||
}
|
||||
|
||||
r = ctx->prep_num_kept_bytes > len ? len : ctx->prep_num_kept_bytes;
|
||||
|
||||
if(ctx->delta_plane_size)
|
||||
{
|
||||
for(i = 0;; ctx->delta_plane_pos++)
|
||||
{
|
||||
for(; ctx->delta_plane < ctx->delta_block_size; ctx->delta_plane += ctx->delta_plane_size, i++)
|
||||
{
|
||||
if(i == r) goto DELTA_BREAK;
|
||||
buf[i] = ctx->prep_kept_bytes_buf[ctx->delta_plane_pos + ctx->delta_plane];
|
||||
}
|
||||
ctx->delta_plane = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DELTA_BREAK:
|
||||
ctx->prep_kept_bytes_pos += r;
|
||||
ctx->prep_num_kept_bytes -= r;
|
||||
|
||||
if(!ctx->prep_num_kept_bytes) ctx->next_type = ctx->over_next_type;
|
||||
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(buf, ctx->prep_kept_bytes_buf, ctx->prep_num_kept_bytes);
|
||||
|
||||
r = ace_lz77_block(ctx, &buf[ctx->prep_num_kept_bytes], len - ctx->prep_num_kept_bytes) +
|
||||
ctx->prep_num_kept_bytes;
|
||||
|
||||
ctx->prep_num_kept_bytes = 0;
|
||||
|
||||
if(ctx->type == ACE_BLOCK_LZ77_EXE)
|
||||
{
|
||||
ctx->exe_mode = ctx->next_exe_mode;
|
||||
|
||||
for(i = 0; i < r - 4; i++)
|
||||
{
|
||||
pos = (int)(ctx->file_pos + i);
|
||||
|
||||
if(buf[i] == (uint8_t)0xe8)
|
||||
{
|
||||
if(!ctx->exe_mode)
|
||||
{
|
||||
uint16_t val;
|
||||
memcpy(&val, &buf[i + 1], 2);
|
||||
val -= (uint16_t)pos;
|
||||
memcpy(&buf[i + 1], &val, 2);
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t val;
|
||||
memcpy(&val, &buf[i + 1], 4);
|
||||
val -= (uint32_t)pos;
|
||||
memcpy(&buf[i + 1], &val, 4);
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
else if(buf[i] == (uint8_t)0xe9)
|
||||
{
|
||||
uint16_t val;
|
||||
memcpy(&val, &buf[i + 1], 2);
|
||||
val -= (uint16_t)pos;
|
||||
memcpy(&buf[i + 1], &val, 2);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
for(; i < r; i++)
|
||||
{
|
||||
if(buf[i] == (uint8_t)0xe8 || buf[i] == (uint8_t)0xe9)
|
||||
{
|
||||
ctx->prep_num_kept_bytes = r - i;
|
||||
memcpy(ctx->prep_kept_bytes_buf, &buf[i], ctx->prep_num_kept_bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return r - ctx->prep_num_kept_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
int ace_decompress_v2(ace_decompress_ctx_t *ctx, const uint8_t *in_buf, size_t in_len, uint8_t *out_buf,
|
||||
size_t *out_len)
|
||||
{
|
||||
size_t orig_size = *out_len;
|
||||
size_t total_out = 0;
|
||||
int r;
|
||||
|
||||
ctx->in_buf = in_buf;
|
||||
ctx->in_len = in_len;
|
||||
ctx->in_pos = 0;
|
||||
ctx->error = 0;
|
||||
ctx->dic_pos = 0;
|
||||
|
||||
ctx->file_size = (int64_t)orig_size;
|
||||
ctx->file_pos = 0;
|
||||
|
||||
ctx->block_size = 0;
|
||||
ctx->part_size = 0;
|
||||
ctx->main_buf_pos = 0;
|
||||
ctx->old_dists_pos = 0;
|
||||
ctx->prep_num_kept_bytes = 0;
|
||||
ctx->prep_last_delta = 0;
|
||||
ctx->delta_block_size = 0;
|
||||
ctx->next_delta_len = 0;
|
||||
memset(ctx->old_dists, 0, sizeof(ctx->old_dists));
|
||||
|
||||
ctx->type = ACE_BLOCK_LZ77_NORM;
|
||||
ctx->next_type = ACE_BLOCK_LZ77_NORM;
|
||||
|
||||
ace_init_read_buf(ctx);
|
||||
|
||||
while(total_out < orig_size && !ctx->error)
|
||||
{
|
||||
int remaining = (int)(orig_size - total_out);
|
||||
|
||||
r = ace_decompress_v20_block(ctx, out_buf + total_out, remaining);
|
||||
if(r <= 0) break;
|
||||
total_out += r;
|
||||
}
|
||||
|
||||
*out_len = total_out;
|
||||
|
||||
ace_pic_done(ctx);
|
||||
|
||||
return ctx->error ? -1 : 0;
|
||||
}
|
||||
301
library.c
301
library.c
@@ -25,15 +25,14 @@
|
||||
#include "3rdparty/bzip2/bzlib.h"
|
||||
#include "3rdparty/lz4/lib/lz4.h"
|
||||
#include "3rdparty/lzfse/src/lzfse.h"
|
||||
#include "3rdparty/lzfse/src/lzvn_encode_base.h"
|
||||
#include "3rdparty/lzfse/src/lzvn_decode_base.h"
|
||||
#include "3rdparty/lzfse/src/lzvn_encode_base.h"
|
||||
#include "3rdparty/lzma/C/7zCrc.h"
|
||||
#include "3rdparty/lzma/C/Alloc.h"
|
||||
#include "3rdparty/lzma/C/LzmaLib.h"
|
||||
#include "3rdparty/lzma/C/Xz.h"
|
||||
#include "3rdparty/lzma/C/XzEnc.h"
|
||||
#include "3rdparty/lzma/C/Alloc.h"
|
||||
#include "3rdparty/lzma/C/7zCrc.h"
|
||||
#include "3rdparty/lzma/C/XzCrc64.h"
|
||||
#include "3rdparty/lzo-2.10/include/lzo/lzoconf.h"
|
||||
#include "3rdparty/lzma/C/XzEnc.h"
|
||||
#include "3rdparty/lzo-2.10/include/lzo/lzo1.h"
|
||||
#include "3rdparty/lzo-2.10/include/lzo/lzo1a.h"
|
||||
#include "3rdparty/lzo-2.10/include/lzo/lzo1b.h"
|
||||
@@ -43,64 +42,38 @@
|
||||
#include "3rdparty/lzo-2.10/include/lzo/lzo1y.h"
|
||||
#include "3rdparty/lzo-2.10/include/lzo/lzo1z.h"
|
||||
#include "3rdparty/lzo-2.10/include/lzo/lzo2a.h"
|
||||
#include "3rdparty/lzo-2.10/include/lzo/lzoconf.h"
|
||||
#include "3rdparty/lzo-2.10/include/lzo/lzodefs.h"
|
||||
#include "3rdparty/zstd/lib/zstd.h"
|
||||
#include "ace/ace.h"
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_decode_buffer(uint8_t * dst_buffer,
|
||||
uint32_t * dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
uint32_t src_size)
|
||||
{
|
||||
return BZ2_bzBuffToBuffDecompress((char *)dst_buffer, dst_size, (char *)src_buffer, src_size, 0, 0);
|
||||
}
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_decode_buffer(uint8_t *dst_buffer, uint32_t *dst_size,
|
||||
const uint8_t *src_buffer, uint32_t src_size)
|
||||
{ return BZ2_bzBuffToBuffDecompress((char *)dst_buffer, dst_size, (char *)src_buffer, src_size, 0, 0); }
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_encode_buffer(uint8_t * dst_buffer,
|
||||
uint32_t * dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
uint32_t src_size,
|
||||
int32_t blockSize100k)
|
||||
{
|
||||
return BZ2_bzBuffToBuffCompress((char *)dst_buffer, dst_size, (char *)src_buffer, src_size, blockSize100k, 0, 0);
|
||||
}
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_bzip2_encode_buffer(uint8_t *dst_buffer, uint32_t *dst_size,
|
||||
const uint8_t *src_buffer, uint32_t src_size,
|
||||
int32_t blockSize100k)
|
||||
{ return BZ2_bzBuffToBuffCompress((char *)dst_buffer, dst_size, (char *)src_buffer, src_size, blockSize100k, 0, 0); }
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lz4_decode_buffer(uint8_t * dst_buffer,
|
||||
int32_t dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
int32_t src_size)
|
||||
{
|
||||
return LZ4_decompress_safe((const char *)src_buffer, (char *)dst_buffer, src_size, dst_size);
|
||||
}
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lz4_decode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer,
|
||||
int32_t src_size)
|
||||
{ return LZ4_decompress_safe((const char *)src_buffer, (char *)dst_buffer, src_size, dst_size); }
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lz4_encode_buffer(uint8_t * dst_buffer,
|
||||
int32_t dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
int32_t src_size)
|
||||
{
|
||||
return LZ4_compress_default((const char *)src_buffer, (char *)dst_buffer, src_size, dst_size);
|
||||
}
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lz4_encode_buffer(uint8_t *dst_buffer, int32_t dst_size, const uint8_t *src_buffer,
|
||||
int32_t src_size)
|
||||
{ return LZ4_compress_default((const char *)src_buffer, (char *)dst_buffer, src_size, dst_size); }
|
||||
|
||||
AARU_EXPORT size_t AARU_CALL AARU_lzfse_decode_buffer(uint8_t * dst_buffer,
|
||||
size_t dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
size_t src_size,
|
||||
void * scratch_buffer)
|
||||
{
|
||||
return lzfse_decode_buffer(dst_buffer, dst_size, src_buffer, src_size, scratch_buffer);
|
||||
}
|
||||
AARU_EXPORT size_t AARU_CALL AARU_lzfse_decode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer,
|
||||
size_t src_size, void *scratch_buffer)
|
||||
{ return lzfse_decode_buffer(dst_buffer, dst_size, src_buffer, src_size, scratch_buffer); }
|
||||
|
||||
AARU_EXPORT size_t AARU_CALL AARU_lzfse_encode_buffer(uint8_t * dst_buffer,
|
||||
size_t dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
size_t src_size,
|
||||
void * scratch_buffer)
|
||||
{
|
||||
return lzfse_encode_buffer(dst_buffer, dst_size, src_buffer, src_size, scratch_buffer);
|
||||
}
|
||||
AARU_EXPORT size_t AARU_CALL AARU_lzfse_encode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer,
|
||||
size_t src_size, void *scratch_buffer)
|
||||
{ return lzfse_encode_buffer(dst_buffer, dst_size, src_buffer, src_size, scratch_buffer); }
|
||||
|
||||
AARU_EXPORT size_t AARU_CALL AARU_lzvn_decode_buffer(uint8_t * dst_buffer,
|
||||
size_t dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
size_t src_size)
|
||||
AARU_EXPORT size_t AARU_CALL AARU_lzvn_decode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer,
|
||||
size_t src_size)
|
||||
{
|
||||
lzvn_decoder_state state;
|
||||
memset(&state, 0, sizeof(state));
|
||||
@@ -117,11 +90,8 @@ AARU_EXPORT size_t AARU_CALL AARU_lzvn_decode_buffer(uint8_t * dst_buffer,
|
||||
return (size_t)(state.dst - dst_buffer);
|
||||
}
|
||||
|
||||
AARU_EXPORT size_t AARU_CALL AARU_lzvn_encode_buffer(uint8_t * dst_buffer,
|
||||
size_t dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
size_t src_size,
|
||||
void * scratch_buffer)
|
||||
AARU_EXPORT size_t AARU_CALL AARU_lzvn_encode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer,
|
||||
size_t src_size, void *scratch_buffer)
|
||||
{
|
||||
lzvn_encoder_state state;
|
||||
memset(&state, 0, sizeof(state));
|
||||
@@ -144,29 +114,14 @@ AARU_EXPORT size_t AARU_CALL AARU_lzvn_encode_buffer(uint8_t * dst_buffer,
|
||||
return (size_t)(state.dst - dst_buffer);
|
||||
}
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lzma_decode_buffer(uint8_t * dst_buffer,
|
||||
size_t * dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
size_t * srcLen,
|
||||
const uint8_t *props,
|
||||
size_t propsSize)
|
||||
{
|
||||
return LzmaUncompress(dst_buffer, dst_size, src_buffer, srcLen, props, propsSize);
|
||||
}
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lzma_decode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer,
|
||||
size_t *srcLen, const uint8_t *props, size_t propsSize)
|
||||
{ return LzmaUncompress(dst_buffer, dst_size, src_buffer, srcLen, props, propsSize); }
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lzma_encode_buffer(uint8_t * dst_buffer,
|
||||
size_t * dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
size_t srcLen,
|
||||
uint8_t * outProps,
|
||||
size_t * outPropsSize,
|
||||
int32_t level,
|
||||
uint32_t dictSize,
|
||||
int32_t lc,
|
||||
int32_t lp,
|
||||
int32_t pb,
|
||||
int32_t fb,
|
||||
int32_t numThreads)
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lzma_encode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer,
|
||||
size_t srcLen, uint8_t *outProps, size_t *outPropsSize,
|
||||
int32_t level, uint32_t dictSize, int32_t lc, int32_t lp,
|
||||
int32_t pb, int32_t fb, int32_t numThreads)
|
||||
{
|
||||
return LzmaCompress(dst_buffer, dst_size, src_buffer, srcLen, outProps, outPropsSize, level, dictSize, lc, lp, pb,
|
||||
fb, numThreads);
|
||||
@@ -176,7 +131,7 @@ AARU_EXPORT int32_t AARU_CALL AARU_lzma_encode_buffer(uint8_t * dst_buffer,
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream vt;
|
||||
const Byte * data;
|
||||
const Byte *data;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} CBufferInStream;
|
||||
@@ -194,7 +149,7 @@ static SRes BufferInStream_Read(ISeqInStreamPtr pp, void *buf, size_t *size)
|
||||
typedef struct
|
||||
{
|
||||
ISeqOutStream vt;
|
||||
Byte * data;
|
||||
Byte *data;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} CBufferOutStream;
|
||||
@@ -220,10 +175,8 @@ static void xz_init_crc_tables(void)
|
||||
}
|
||||
}
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_xz_decode_buffer(uint8_t * dst_buffer,
|
||||
size_t * dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
size_t src_size)
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_xz_decode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer,
|
||||
size_t src_size)
|
||||
{
|
||||
CXzUnpacker state;
|
||||
SizeT destLen = (SizeT)*dst_size;
|
||||
@@ -245,12 +198,8 @@ AARU_EXPORT int32_t AARU_CALL AARU_xz_decode_buffer(uint8_t * dst_buffer,
|
||||
return res;
|
||||
}
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_xz_encode_buffer(uint8_t * dst_buffer,
|
||||
size_t * dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
size_t src_size,
|
||||
uint32_t preset,
|
||||
uint32_t checkType)
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_xz_encode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer,
|
||||
size_t src_size, uint32_t preset, uint32_t checkType)
|
||||
{
|
||||
CXzProps props;
|
||||
CBufferInStream inStream;
|
||||
@@ -280,33 +229,21 @@ AARU_EXPORT int32_t AARU_CALL AARU_xz_encode_buffer(uint8_t * dst_buffer,
|
||||
return res;
|
||||
}
|
||||
|
||||
AARU_EXPORT size_t AARU_CALL AARU_zstd_decode_buffer(void * dst_buffer,
|
||||
size_t dst_size,
|
||||
const void *src_buffer,
|
||||
size_t src_size)
|
||||
{
|
||||
return ZSTD_decompress(dst_buffer, dst_size, src_buffer, src_size);
|
||||
}
|
||||
AARU_EXPORT size_t AARU_CALL AARU_zstd_decode_buffer(void *dst_buffer, size_t dst_size, const void *src_buffer,
|
||||
size_t src_size)
|
||||
{ return ZSTD_decompress(dst_buffer, dst_size, src_buffer, src_size); }
|
||||
|
||||
AARU_EXPORT size_t AARU_CALL AARU_zstd_encode_buffer(void * dst_buffer,
|
||||
size_t dst_size,
|
||||
const void *src_buffer,
|
||||
size_t src_size,
|
||||
int32_t compressionLevel)
|
||||
{
|
||||
return ZSTD_compress(dst_buffer, dst_size, src_buffer, src_size, compressionLevel);
|
||||
}
|
||||
AARU_EXPORT size_t AARU_CALL AARU_zstd_encode_buffer(void *dst_buffer, size_t dst_size, const void *src_buffer,
|
||||
size_t src_size, int32_t compressionLevel)
|
||||
{ return ZSTD_compress(dst_buffer, dst_size, src_buffer, src_size, compressionLevel); }
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lzo_decode_buffer(uint8_t * dst_buffer,
|
||||
size_t * dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
size_t src_size,
|
||||
int32_t algorithm)
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lzo_decode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer,
|
||||
size_t src_size, int32_t algorithm)
|
||||
{
|
||||
lzo_uint out_len = *dst_size;
|
||||
|
||||
int result = lzo_init();
|
||||
if(result != LZO_E_OK) return result; // Initialization failed
|
||||
if(result != LZO_E_OK) return result; // Initialization failed
|
||||
|
||||
switch(algorithm)
|
||||
{
|
||||
@@ -338,59 +275,74 @@ AARU_EXPORT int32_t AARU_CALL AARU_lzo_decode_buffer(uint8_t * dst_buffer,
|
||||
result = lzo2a_decompress_safe(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, NULL);
|
||||
break;
|
||||
default:
|
||||
return -1; // Invalid algorithm
|
||||
return -1; // Invalid algorithm
|
||||
}
|
||||
|
||||
*dst_size = out_len;
|
||||
return result;
|
||||
}
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lzo_encode_buffer(uint8_t * dst_buffer,
|
||||
size_t * dst_size,
|
||||
const uint8_t *src_buffer,
|
||||
size_t src_size,
|
||||
int32_t algorithm,
|
||||
int32_t compression_level)
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_lzo_encode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer,
|
||||
size_t src_size, int32_t algorithm, int32_t compression_level)
|
||||
{
|
||||
lzo_uint out_len = *dst_size;
|
||||
void * wrkmem = NULL;
|
||||
void *wrkmem = NULL;
|
||||
size_t wrkmem_size = 0;
|
||||
|
||||
// Determine work memory size based on algorithm and compression level
|
||||
switch(algorithm)
|
||||
{
|
||||
case AARU_LZO_ALGORITHM_LZO1:
|
||||
if(compression_level == 99) wrkmem_size = LZO1_99_MEM_COMPRESS;
|
||||
else wrkmem_size = LZO1_MEM_COMPRESS;
|
||||
if(compression_level == 99)
|
||||
wrkmem_size = LZO1_99_MEM_COMPRESS;
|
||||
else
|
||||
wrkmem_size = LZO1_MEM_COMPRESS;
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1A:
|
||||
if(compression_level == 99) wrkmem_size = LZO1A_99_MEM_COMPRESS;
|
||||
else wrkmem_size = LZO1A_MEM_COMPRESS;
|
||||
if(compression_level == 99)
|
||||
wrkmem_size = LZO1A_99_MEM_COMPRESS;
|
||||
else
|
||||
wrkmem_size = LZO1A_MEM_COMPRESS;
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1B:
|
||||
if(compression_level == 99) wrkmem_size = LZO1B_99_MEM_COMPRESS;
|
||||
else if(compression_level == 999) wrkmem_size = LZO1B_999_MEM_COMPRESS;
|
||||
else wrkmem_size = LZO1B_MEM_COMPRESS;
|
||||
if(compression_level == 99)
|
||||
wrkmem_size = LZO1B_99_MEM_COMPRESS;
|
||||
else if(compression_level == 999)
|
||||
wrkmem_size = LZO1B_999_MEM_COMPRESS;
|
||||
else
|
||||
wrkmem_size = LZO1B_MEM_COMPRESS;
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1C:
|
||||
if(compression_level == 99) wrkmem_size = LZO1C_99_MEM_COMPRESS;
|
||||
else if(compression_level == 999) wrkmem_size = LZO1C_999_MEM_COMPRESS;
|
||||
else wrkmem_size = LZO1C_MEM_COMPRESS;
|
||||
if(compression_level == 99)
|
||||
wrkmem_size = LZO1C_99_MEM_COMPRESS;
|
||||
else if(compression_level == 999)
|
||||
wrkmem_size = LZO1C_999_MEM_COMPRESS;
|
||||
else
|
||||
wrkmem_size = LZO1C_MEM_COMPRESS;
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1F:
|
||||
if(compression_level == 999) wrkmem_size = LZO1F_999_MEM_COMPRESS;
|
||||
else wrkmem_size = LZO1F_MEM_COMPRESS;
|
||||
if(compression_level == 999)
|
||||
wrkmem_size = LZO1F_999_MEM_COMPRESS;
|
||||
else
|
||||
wrkmem_size = LZO1F_MEM_COMPRESS;
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1X:
|
||||
if(compression_level == 11) wrkmem_size = LZO1X_1_11_MEM_COMPRESS;
|
||||
else if(compression_level == 12) wrkmem_size = LZO1X_1_12_MEM_COMPRESS;
|
||||
else if(compression_level == 15) wrkmem_size = LZO1X_1_15_MEM_COMPRESS;
|
||||
else if(compression_level == 999) wrkmem_size = LZO1X_999_MEM_COMPRESS;
|
||||
else wrkmem_size = LZO1X_1_MEM_COMPRESS;
|
||||
if(compression_level == 11)
|
||||
wrkmem_size = LZO1X_1_11_MEM_COMPRESS;
|
||||
else if(compression_level == 12)
|
||||
wrkmem_size = LZO1X_1_12_MEM_COMPRESS;
|
||||
else if(compression_level == 15)
|
||||
wrkmem_size = LZO1X_1_15_MEM_COMPRESS;
|
||||
else if(compression_level == 999)
|
||||
wrkmem_size = LZO1X_999_MEM_COMPRESS;
|
||||
else
|
||||
wrkmem_size = LZO1X_1_MEM_COMPRESS;
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1Y:
|
||||
if(compression_level == 999) wrkmem_size = LZO1Y_999_MEM_COMPRESS;
|
||||
else wrkmem_size = LZO1Y_MEM_COMPRESS;
|
||||
if(compression_level == 999)
|
||||
wrkmem_size = LZO1Y_999_MEM_COMPRESS;
|
||||
else
|
||||
wrkmem_size = LZO1Y_MEM_COMPRESS;
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1Z:
|
||||
wrkmem_size = LZO1Z_999_MEM_COMPRESS;
|
||||
@@ -399,11 +351,11 @@ AARU_EXPORT int32_t AARU_CALL AARU_lzo_encode_buffer(uint8_t * dst_buffer,
|
||||
wrkmem_size = LZO2A_999_MEM_COMPRESS;
|
||||
break;
|
||||
default:
|
||||
return -1; // Invalid algorithm
|
||||
return -1; // Invalid algorithm
|
||||
}
|
||||
|
||||
int result = lzo_init();
|
||||
if(result != LZO_E_OK) return result; // Initialization failed
|
||||
if(result != LZO_E_OK) return result; // Initialization failed
|
||||
|
||||
wrkmem = malloc(wrkmem_size);
|
||||
if(wrkmem == NULL) return -1;
|
||||
@@ -413,13 +365,15 @@ AARU_EXPORT int32_t AARU_CALL AARU_lzo_encode_buffer(uint8_t * dst_buffer,
|
||||
{
|
||||
case AARU_LZO_ALGORITHM_LZO1:
|
||||
if(compression_level == 99)
|
||||
result = lzo1_99_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else result = lzo1_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
result = lzo1_99_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else
|
||||
result = lzo1_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1A:
|
||||
if(compression_level == 99)
|
||||
result = lzo1a_99_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else result = lzo1a_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
result = lzo1a_99_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else
|
||||
result = lzo1a_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1B:
|
||||
if(compression_level == 99)
|
||||
@@ -427,8 +381,8 @@ AARU_EXPORT int32_t AARU_CALL AARU_lzo_encode_buffer(uint8_t * dst_buffer,
|
||||
else if(compression_level == 999)
|
||||
result = lzo1b_999_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else if(compression_level >= 1 && compression_level <= 9)
|
||||
result = lzo1b_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem,
|
||||
compression_level);
|
||||
result =
|
||||
lzo1b_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem, compression_level);
|
||||
else
|
||||
result = lzo1b_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem,
|
||||
LZO1B_DEFAULT_COMPRESSION);
|
||||
@@ -439,16 +393,17 @@ AARU_EXPORT int32_t AARU_CALL AARU_lzo_encode_buffer(uint8_t * dst_buffer,
|
||||
else if(compression_level == 999)
|
||||
result = lzo1c_999_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else if(compression_level >= 1 && compression_level <= 9)
|
||||
result = lzo1c_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem,
|
||||
compression_level);
|
||||
result =
|
||||
lzo1c_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem, compression_level);
|
||||
else
|
||||
result = lzo1c_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem,
|
||||
LZO1C_DEFAULT_COMPRESSION);
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1F:
|
||||
if(compression_level == 999)
|
||||
result = lzo1f_999_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else result = lzo1f_1_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
result = lzo1f_999_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else
|
||||
result = lzo1f_1_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1X:
|
||||
if(compression_level == 11)
|
||||
@@ -458,13 +413,15 @@ AARU_EXPORT int32_t AARU_CALL AARU_lzo_encode_buffer(uint8_t * dst_buffer,
|
||||
else if(compression_level == 15)
|
||||
result = lzo1x_1_15_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else if(compression_level == 999)
|
||||
result = lzo1x_999_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else result = lzo1x_1_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
result = lzo1x_999_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else
|
||||
result = lzo1x_1_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1Y:
|
||||
if(compression_level == 999)
|
||||
result = lzo1y_999_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else result = lzo1y_1_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
result = lzo1y_999_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
else
|
||||
result = lzo1y_1_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
break;
|
||||
case AARU_LZO_ALGORITHM_LZO1Z:
|
||||
result = lzo1z_999_compress(src_buffer, (lzo_uint)src_size, dst_buffer, &out_len, wrkmem);
|
||||
@@ -474,7 +431,7 @@ AARU_EXPORT int32_t AARU_CALL AARU_lzo_encode_buffer(uint8_t * dst_buffer,
|
||||
break;
|
||||
default:
|
||||
free(wrkmem);
|
||||
return -1; // Invalid algorithm
|
||||
return -1; // Invalid algorithm
|
||||
}
|
||||
|
||||
free(wrkmem);
|
||||
@@ -485,4 +442,32 @@ AARU_EXPORT int32_t AARU_CALL AARU_lzo_encode_buffer(uint8_t * dst_buffer,
|
||||
// This is required if BZ_NO_STDIO
|
||||
void bz_internal_error(int errcode) {}
|
||||
|
||||
AARU_EXPORT int AARU_CALL ace_decompress_lz77(const uint8_t *in_buf, size_t in_len, uint8_t *out_buf, size_t *out_len,
|
||||
int dic_bits)
|
||||
{
|
||||
ace_decompress_ctx_t ctx;
|
||||
int ret;
|
||||
|
||||
if(ace_decompress_init(&ctx, dic_bits) != 0) return -1;
|
||||
|
||||
ret = ace_decompress_v1(&ctx, in_buf, in_len, out_buf, out_len);
|
||||
ace_decompress_free(&ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AARU_EXPORT int AARU_CALL ace_decompress_blocked(const uint8_t *in_buf, size_t in_len, uint8_t *out_buf,
|
||||
size_t *out_len, int dic_bits)
|
||||
{
|
||||
ace_decompress_ctx_t ctx;
|
||||
int ret;
|
||||
|
||||
if(ace_decompress_init(&ctx, dic_bits) != 0) return -1;
|
||||
|
||||
ret = ace_decompress_v2(&ctx, in_buf, in_len, out_buf, out_len);
|
||||
ace_decompress_free(&ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AARU_EXPORT uint64_t AARU_CALL AARU_get_acn_version() { return AARU_CHECKUMS_NATIVE_VERSION; }
|
||||
@@ -234,4 +234,10 @@ AARU_EXPORT int AARU_CALL pmarc_decompress_pm1(const uint8_t *in_buf, size_t in_
|
||||
// PMarc -pm2- (Dynamic trees + history, legacy)
|
||||
AARU_EXPORT int AARU_CALL pmarc_decompress_pm2(const uint8_t *in_buf, size_t in_len, uint8_t *out_buf, size_t *out_len);
|
||||
|
||||
// ACE v1 (LZ77) decompression
|
||||
AARU_EXPORT int AARU_CALL ace_decompress_lz77(const uint8_t *in_buf, size_t in_len, uint8_t *out_buf, size_t *out_len, int dic_bits);
|
||||
|
||||
// ACE v2 (Blocked) decompression
|
||||
AARU_EXPORT int AARU_CALL ace_decompress_blocked(const uint8_t *in_buf, size_t in_len, uint8_t *out_buf, size_t *out_len, int dic_bits);
|
||||
|
||||
#endif // AARU_COMPRESSION_NATIVE_LIBRARY_H
|
||||
|
||||
@@ -90,10 +90,17 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/lharc_lh1.lzh
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/pmarc_pm2.pma
|
||||
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/ace_v1_lz77.bin
|
||||
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/ace_v2_blocked.bin
|
||||
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
|
||||
|
||||
# 'Google_Tests_run' is the target name
|
||||
# 'test1.cpp tests2.cpp' are source files with tests
|
||||
add_executable(tests_run apple_rle.cpp crc32.c crc32.h adc.cpp bzip2.cpp lzip.cpp lzfse.cpp zstd.cpp lzma.cpp flac.cpp lz4.cpp
|
||||
zoo/lzd.cpp arc/pack.cpp lh5.cpp arc/squeeze.cpp arc/crunch.cpp arc/squash.cpp pak/crush.cpp
|
||||
pak/distill.cpp ha.cpp xz.cpp
|
||||
lha/lh_static.cpp lha/lh1.cpp lha/larc.cpp lha/lh_old.cpp)
|
||||
lha/lh_static.cpp lha/lh1.cpp lha/larc.cpp lha/lh_old.cpp
|
||||
ace/ace.cpp)
|
||||
target_link_libraries(tests_run gtest gtest_main "Aaru.Compression.Native")
|
||||
|
||||
116
tests/ace/ace.cpp
Normal file
116
tests/ace/ace.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This file is part of the Aaru Data Preservation Suite.
|
||||
* Copyright (c) 2019-2026 Natalia Portillo.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include "../../library.h"
|
||||
#include "../crc32.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#define EXPECTED_CRC32 0x66007dba
|
||||
|
||||
static const uint8_t *buffer_v1;
|
||||
static const uint8_t *buffer_v2;
|
||||
|
||||
class ace_v1Fixture : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
ace_v1Fixture() {}
|
||||
|
||||
protected:
|
||||
void SetUp()
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char filename[PATH_MAX];
|
||||
|
||||
getcwd(path, PATH_MAX);
|
||||
snprintf(filename, PATH_MAX, "%s/data/ace_v1_lz77.bin", path);
|
||||
|
||||
FILE *file = fopen(filename, "rb");
|
||||
buffer_v1 = (const uint8_t *)malloc(54904);
|
||||
fread((void *)buffer_v1, 1, 54904, file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
void TearDown() { free((void *)buffer_v1); }
|
||||
|
||||
~ace_v1Fixture() {}
|
||||
};
|
||||
|
||||
TEST_F(ace_v1Fixture, ace_v1_lz77)
|
||||
{
|
||||
size_t destLen = 152089;
|
||||
size_t srcLen = 54904;
|
||||
auto *outBuf = (uint8_t *)malloc(152089);
|
||||
|
||||
auto err = ace_decompress_lz77(buffer_v1, srcLen, outBuf, &destLen, 20);
|
||||
|
||||
EXPECT_EQ(err, 0);
|
||||
EXPECT_EQ(destLen, 152089);
|
||||
|
||||
auto crc = crc32_data(outBuf, 152089);
|
||||
|
||||
free(outBuf);
|
||||
|
||||
EXPECT_EQ(crc, EXPECTED_CRC32);
|
||||
}
|
||||
|
||||
class ace_v2Fixture : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
ace_v2Fixture() {}
|
||||
|
||||
protected:
|
||||
void SetUp()
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char filename[PATH_MAX];
|
||||
|
||||
getcwd(path, PATH_MAX);
|
||||
snprintf(filename, PATH_MAX, "%s/data/ace_v2_blocked.bin", path);
|
||||
|
||||
FILE *file = fopen(filename, "rb");
|
||||
buffer_v2 = (const uint8_t *)malloc(50984);
|
||||
fread((void *)buffer_v2, 1, 50984, file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
void TearDown() { free((void *)buffer_v2); }
|
||||
|
||||
~ace_v2Fixture() {}
|
||||
};
|
||||
|
||||
TEST_F(ace_v2Fixture, ace_v2_blocked)
|
||||
{
|
||||
size_t destLen = 152089;
|
||||
size_t srcLen = 50984;
|
||||
auto *outBuf = (uint8_t *)malloc(152089);
|
||||
|
||||
auto err = ace_decompress_blocked(buffer_v2, srcLen, outBuf, &destLen, 20);
|
||||
|
||||
EXPECT_EQ(err, 0);
|
||||
EXPECT_EQ(destLen, 152089);
|
||||
|
||||
auto crc = crc32_data(outBuf, 152089);
|
||||
|
||||
free(outBuf);
|
||||
|
||||
EXPECT_EQ(crc, EXPECTED_CRC32);
|
||||
}
|
||||
BIN
tests/data/ace_v1_lz77.bin
Normal file
BIN
tests/data/ace_v1_lz77.bin
Normal file
Binary file not shown.
BIN
tests/data/ace_v2_blocked.bin
Normal file
BIN
tests/data/ace_v2_blocked.bin
Normal file
Binary file not shown.
Reference in New Issue
Block a user