mirror of
https://github.com/SimoneN64/Kaizen.git
synced 2025-04-02 10:41:53 -04:00
243 lines
6 KiB
C
243 lines
6 KiB
C
/* Copyright 2015 the unarr project authors (see AUTHORS file).
|
|
License: LGPLv3 */
|
|
|
|
#ifndef rar_rar_h
|
|
#define rar_rar_h
|
|
|
|
#include "../common/unarr-imp.h"
|
|
|
|
#include "lzss.h"
|
|
#include "../lzmasdk/Ppmd7.h"
|
|
#include <limits.h>
|
|
|
|
static inline size_t smin(size_t a, size_t b) { return a < b ? a : b; }
|
|
|
|
typedef struct ar_archive_rar_s ar_archive_rar;
|
|
|
|
/***** parse-rar *****/
|
|
|
|
#define FILE_SIGNATURE_SIZE 7
|
|
|
|
enum block_types {
|
|
TYPE_FILE_SIGNATURE = 0x72, TYPE_MAIN_HEADER = 0x73, TYPE_FILE_ENTRY = 0x74,
|
|
TYPE_NEWSUB = 0x7A, TYPE_END_OF_ARCHIVE = 0x7B,
|
|
};
|
|
|
|
enum archive_flags {
|
|
MHD_VOLUME = 1 << 0, MHD_COMMENT = 1 << 1, MHD_LOCK = 1 << 2,
|
|
MHD_SOLID = 1 << 3, MHD_PACK_COMMENT = 1 << 4, MHD_AV = 1 << 5,
|
|
MHD_PROTECT = 1 << 6, MHD_PASSWORD = 1 << 7, MHD_FIRSTVOLUME = 1 << 8,
|
|
MHD_ENCRYPTVER = 1 << 9,
|
|
MHD_LONG_BLOCK = 1 << 15,
|
|
};
|
|
|
|
enum entry_flags {
|
|
LHD_SPLIT_BEFORE = 1 << 0, LHD_SPLIT_AFTER = 1 << 1, LHD_PASSWORD = 1 << 2,
|
|
LHD_COMMENT = 1 << 3, LHD_SOLID = 1 << 4,
|
|
LHD_DIRECTORY = (1 << 5) | (1 << 6) | (1 << 7),
|
|
LHD_LARGE = 1 << 8, LHD_UNICODE = 1 << 9, LHD_SALT = 1 << 10,
|
|
LHD_VERSION = 1 << 11, LHD_EXTTIME = 1 << 12, LHD_EXTFLAGS = 1 << 13,
|
|
LHD_LONG_BLOCK = 1 << 15,
|
|
};
|
|
|
|
enum compression_method {
|
|
METHOD_STORE = 0x30,
|
|
METHOD_FASTEST = 0x31, METHOD_FAST = 0x32, METHOD_NORMAL = 0x33,
|
|
METHOD_GOOD = 0x34, METHOD_BEST = 0x35,
|
|
};
|
|
|
|
struct rar_header {
|
|
uint16_t crc;
|
|
uint8_t type;
|
|
uint16_t flags;
|
|
uint16_t size;
|
|
uint64_t datasize;
|
|
};
|
|
|
|
struct rar_entry {
|
|
uint64_t size;
|
|
uint8_t os;
|
|
uint32_t crc;
|
|
uint32_t dosdate;
|
|
uint8_t version;
|
|
uint8_t method;
|
|
uint16_t namelen;
|
|
uint32_t attrs;
|
|
};
|
|
|
|
struct ar_archive_rar_entry {
|
|
uint8_t version;
|
|
uint8_t method;
|
|
uint32_t crc;
|
|
uint16_t header_size;
|
|
bool solid;
|
|
char *name;
|
|
};
|
|
|
|
bool rar_parse_header(ar_archive *ar, struct rar_header *header);
|
|
bool rar_check_header_crc(ar_archive *ar);
|
|
bool rar_parse_header_entry(ar_archive_rar *rar, struct rar_header *header, struct rar_entry *entry);
|
|
const char *rar_get_name(ar_archive *ar, bool raw);
|
|
|
|
/***** filter-rar *****/
|
|
|
|
struct RARVirtualMachine;
|
|
struct RARProgramCode;
|
|
struct RARFilter;
|
|
|
|
struct ar_archive_rar_filters {
|
|
struct RARVirtualMachine *vm;
|
|
struct RARProgramCode *progs;
|
|
struct RARFilter *stack;
|
|
size_t filterstart;
|
|
uint32_t lastfilternum;
|
|
size_t lastend;
|
|
uint8_t *bytes;
|
|
size_t bytes_ready;
|
|
};
|
|
|
|
bool rar_parse_filter(ar_archive_rar *rar, const uint8_t *bytes, uint16_t length, uint8_t flags);
|
|
bool rar_run_filters(ar_archive_rar *rar);
|
|
void rar_clear_filters(struct ar_archive_rar_filters *filters);
|
|
|
|
/***** huffman-rar *****/
|
|
|
|
struct huffman_code {
|
|
struct {
|
|
int branches[2];
|
|
} *tree;
|
|
int numentries;
|
|
int capacity;
|
|
int minlength;
|
|
int maxlength;
|
|
struct {
|
|
int length;
|
|
int value;
|
|
} *table;
|
|
int tablesize;
|
|
};
|
|
|
|
bool rar_new_node(struct huffman_code *code);
|
|
bool rar_add_value(struct huffman_code *code, int value, int codebits, int length);
|
|
bool rar_create_code(struct huffman_code *code, uint8_t *lengths, int numsymbols);
|
|
bool rar_make_table(struct huffman_code *code);
|
|
void rar_free_code(struct huffman_code *code);
|
|
|
|
static inline bool rar_is_leaf_node(struct huffman_code *code, int node) { return code->tree[node].branches[0] == code->tree[node].branches[1]; }
|
|
|
|
/***** uncompress-rar *****/
|
|
|
|
#define LZSS_WINDOW_SIZE 0x400000
|
|
#define LZSS_OVERFLOW_SIZE 288
|
|
|
|
#define MAINCODE_SIZE 299
|
|
#define OFFSETCODE_SIZE 60
|
|
#define LOWOFFSETCODE_SIZE 17
|
|
#define LENGTHCODE_SIZE 28
|
|
#define HUFFMAN_TABLE_SIZE MAINCODE_SIZE + OFFSETCODE_SIZE + LOWOFFSETCODE_SIZE + LENGTHCODE_SIZE
|
|
|
|
struct ByteReader {
|
|
IByteIn super;
|
|
ar_archive_rar *rar;
|
|
};
|
|
|
|
struct ar_archive_rar_uncomp_v3 {
|
|
struct huffman_code maincode;
|
|
struct huffman_code offsetcode;
|
|
struct huffman_code lowoffsetcode;
|
|
struct huffman_code lengthcode;
|
|
uint8_t lengthtable[HUFFMAN_TABLE_SIZE];
|
|
uint32_t lastlength;
|
|
uint32_t lastoffset;
|
|
uint32_t oldoffset[4];
|
|
uint32_t lastlowoffset;
|
|
uint32_t numlowoffsetrepeats;
|
|
|
|
bool is_ppmd_block;
|
|
int ppmd_escape;
|
|
CPpmd7 ppmd7_context;
|
|
struct ByteReader bytein;
|
|
|
|
struct ar_archive_rar_filters filters;
|
|
};
|
|
|
|
#define MAINCODE_SIZE_20 298
|
|
#define OFFSETCODE_SIZE_20 48
|
|
#define LENGTHCODE_SIZE_20 28
|
|
#define HUFFMAN_TABLE_SIZE_20 4 * 257
|
|
|
|
struct AudioState {
|
|
int8_t weight[5];
|
|
int16_t delta[4];
|
|
int8_t lastdelta;
|
|
int error[11];
|
|
int count;
|
|
uint8_t lastbyte;
|
|
};
|
|
|
|
struct ar_archive_rar_uncomp_v2 {
|
|
struct huffman_code maincode;
|
|
struct huffman_code offsetcode;
|
|
struct huffman_code lengthcode;
|
|
struct huffman_code audiocode[4];
|
|
uint8_t lengthtable[HUFFMAN_TABLE_SIZE_20];
|
|
uint32_t lastoffset;
|
|
uint32_t lastlength;
|
|
uint32_t oldoffset[4];
|
|
uint32_t oldoffsetindex;
|
|
|
|
bool audioblock;
|
|
uint8_t channel;
|
|
uint8_t numchannels;
|
|
struct AudioState audiostate[4];
|
|
int8_t channeldelta;
|
|
};
|
|
|
|
struct ar_archive_rar_uncomp {
|
|
uint8_t version;
|
|
|
|
LZSS lzss;
|
|
size_t bytes_ready;
|
|
bool start_new_table;
|
|
|
|
union {
|
|
struct ar_archive_rar_uncomp_v3 v3;
|
|
struct ar_archive_rar_uncomp_v2 v2;
|
|
} state;
|
|
|
|
struct StreamBitReader {
|
|
uint64_t bits;
|
|
int available;
|
|
bool at_eof;
|
|
} br;
|
|
};
|
|
|
|
bool rar_uncompress_part(ar_archive_rar *rar, void *buffer, size_t buffer_size);
|
|
int64_t rar_expand(ar_archive_rar *rar, int64_t end);
|
|
void rar_clear_uncompress(struct ar_archive_rar_uncomp *uncomp);
|
|
static inline void br_clear_leftover_bits(struct ar_archive_rar_uncomp *uncomp) { uncomp->br.available &= ~0x07; }
|
|
|
|
/***** rar *****/
|
|
|
|
struct ar_archive_rar_progress {
|
|
size_t data_left;
|
|
size_t bytes_done;
|
|
uint32_t crc;
|
|
};
|
|
|
|
struct ar_archive_rar_solid {
|
|
size_t size_total;
|
|
bool part_done;
|
|
bool restart;
|
|
};
|
|
|
|
struct ar_archive_rar_s {
|
|
ar_archive super;
|
|
uint16_t archive_flags;
|
|
struct ar_archive_rar_entry entry;
|
|
struct ar_archive_rar_uncomp uncomp;
|
|
struct ar_archive_rar_progress progress;
|
|
struct ar_archive_rar_solid solid;
|
|
};
|
|
|
|
#endif
|