| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 | 
							- /*
 
- Copyright (c) 2011, 2012, Simon Howard
 
- Permission to use, copy, modify, and/or distribute this software
 
- for any purpose with or without fee is hereby granted, provided
 
- that the above copyright notice and this permission notice appear
 
- in all copies.
 
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 
- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 
- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 
- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
 
- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 
- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 
- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-  */
 
- #include <stdlib.h>
 
- #include <string.h>
 
- #include <inttypes.h>
 
- #include "lha_decoder.h"
 
- #include "bit_stream_reader.c"
 
- // Parameters for ring buffer, used for storing history.  This acts
 
- // as the dictionary for copy operations.
 
- #define RING_BUFFER_SIZE 2048
 
- #define START_OFFSET 17
 
- // Threshold offset.  In the copy operation, the copy length is a 4-bit
 
- // value, giving a range 0..15.  The threshold offsets this so that it
 
- // is interpreted as 2..17 - a more useful range.
 
- #define THRESHOLD 2
 
- // Size of output buffer.  Must be large enough to hold the results of
 
- // the maximum copy operation.
 
- #define OUTPUT_BUFFER_SIZE (15 + THRESHOLD)
 
- // Decoder for the -lzs- compression method used by old versions of LArc.
 
- //
 
- // The input stream consists of commands, each of which is either "output
 
- // a literal byte value" or "copy block". A bit at the start of each
 
- // command signals which command it is.
 
- typedef struct {
 
- 	BitStreamReader bit_stream_reader;
 
- 	uint8_t ringbuf[RING_BUFFER_SIZE];
 
- 	unsigned int ringbuf_pos;
 
- } LHALZSDecoder;
 
- static int lha_lzs_init(void *data, LHADecoderCallback callback,
 
-                         void *callback_data)
 
- {
 
- 	LHALZSDecoder *decoder = data;
 
- 	memset(decoder->ringbuf, ' ', RING_BUFFER_SIZE);
 
- 	decoder->ringbuf_pos = RING_BUFFER_SIZE - START_OFFSET;
 
- 	bit_stream_reader_init(&decoder->bit_stream_reader, callback,
 
- 	                       callback_data);
 
- 	return 1;
 
- }
 
- // Add a single byte to the output buffer.
 
- static void output_byte(LHALZSDecoder *decoder, uint8_t *buf,
 
-                         size_t *buf_len, uint8_t b)
 
- {
 
- 	buf[*buf_len] = b;
 
- 	++*buf_len;
 
- 	decoder->ringbuf[decoder->ringbuf_pos] = b;
 
- 	decoder->ringbuf_pos = (decoder->ringbuf_pos + 1) % RING_BUFFER_SIZE;
 
- }
 
- // Output a "block" of data from the specified range in the ring buffer.
 
- static void output_block(LHALZSDecoder *decoder,
 
-                          uint8_t *buf,
 
-                          size_t *buf_len,
 
-                          unsigned int start,
 
-                          unsigned int len)
 
- {
 
- 	unsigned int i;
 
- 	for (i = 0; i < len; ++i) {
 
- 		output_byte(decoder, buf, buf_len,
 
- 		            decoder->ringbuf[(start + i) % RING_BUFFER_SIZE]);
 
- 	}
 
- }
 
- // Process a single command from the LZS input stream.
 
- static size_t lha_lzs_read(void *data, uint8_t *buf)
 
- {
 
- 	LHALZSDecoder *decoder = data;
 
- 	int bit;
 
- 	size_t result;
 
- 	// Start from an empty buffer.
 
- 	result = 0;
 
- 	// Each command starts with a bit that signals the type:
 
- 	bit = read_bit(&decoder->bit_stream_reader);
 
- 	if (bit < 0) {
 
- 		return 0;
 
- 	}
 
- 	// What type of command is this?
 
- 	if (bit) {
 
- 		int b;
 
- 		b = read_bits(&decoder->bit_stream_reader, 8);
 
- 		if (b < 0) {
 
- 			return 0;
 
- 		}
 
- 		output_byte(decoder, buf, &result, (uint8_t) b);
 
- 	} else {
 
- 		int pos, len;
 
- 		pos = read_bits(&decoder->bit_stream_reader, 11);
 
- 		len = read_bits(&decoder->bit_stream_reader, 4);
 
- 		if (pos < 0 || len < 0) {
 
- 			return 0;
 
- 		}
 
- 		output_block(decoder, buf, &result, (unsigned int) pos,
 
- 		             (unsigned int) len + THRESHOLD);
 
- 	}
 
- 	return result;
 
- }
 
- LHADecoderType lha_lzs_decoder = {
 
- 	lha_lzs_init,
 
- 	NULL,
 
- 	lha_lzs_read,
 
- 	sizeof(LHALZSDecoder),
 
- 	OUTPUT_BUFFER_SIZE,
 
- 	RING_BUFFER_SIZE
 
- };
 
 
  |