diff options
author | Clyne Sullivan <clyne@bitgloo.com> | 2023-11-05 07:20:04 -0500 |
---|---|---|
committer | Clyne Sullivan <clyne@bitgloo.com> | 2023-11-05 07:20:04 -0500 |
commit | 7e10d0855c3ac6cc08e9089a731aa6f2a2fd4175 (patch) | |
tree | 2f3d13c45c46d078c4aabd7e4a9b313b88183fed /msp430/lzss.c | |
parent | 789791692a20e4da7b798a249ca24ed35cd78b5f (diff) |
msp430: add compressed register/flag wordset
Diffstat (limited to 'msp430/lzss.c')
-rw-r--r-- | msp430/lzss.c | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/msp430/lzss.c b/msp430/lzss.c new file mode 100644 index 0000000..9b64d38 --- /dev/null +++ b/msp430/lzss.c @@ -0,0 +1,181 @@ +/* LZSS encoder-decoder (Haruhiko Okumura; public domain) */ + +#include <stdio.h> +#include <stdlib.h> + +#define EI 8 /* typically 10..13 */ +#define EJ 3 /* typically 4..5 */ +#define P 1 /* If match length <= P then output one character */ +#define N (1 << EI) /* buffer size */ +#define F ((1 << EJ) + 1) /* lookahead buffer size */ + +int bit_buffer = 0, bit_mask = 128; +unsigned long codecount = 0, textcount = 0; +unsigned char buffer[N * 2]; +FILE *infile, *outfile; + +void error(void) +{ + printf("Output error\n"); exit(1); +} + +void putbit1(void) +{ + bit_buffer |= bit_mask; + if ((bit_mask >>= 1) == 0) { + if (fputc(bit_buffer, outfile) == EOF) error(); + bit_buffer = 0; bit_mask = 128; codecount++; + } +} + +void putbit0(void) +{ + if ((bit_mask >>= 1) == 0) { + if (fputc(bit_buffer, outfile) == EOF) error(); + bit_buffer = 0; bit_mask = 128; codecount++; + } +} + +void flush_bit_buffer(void) +{ + if (bit_mask != 128) { + if (fputc(bit_buffer, outfile) == EOF) error(); + codecount++; + } +} + +void output1(int c) +{ + int mask; + + putbit1(); + mask = 256; + while (mask >>= 1) { + if (c & mask) putbit1(); + else putbit0(); + } +} + +void output2(int x, int y) +{ + int mask; + + putbit0(); + mask = N; + while (mask >>= 1) { + if (x & mask) putbit1(); + else putbit0(); + } + mask = (1 << EJ); + while (mask >>= 1) { + if (y & mask) putbit1(); + else putbit0(); + } +} + +void encode(void) +{ + int i, j, f1, x, y, r, s, bufferend, c; + + for (i = 0; i < N - F; i++) buffer[i] = ' '; + for (i = N - F; i < N * 2; i++) { + if ((c = fgetc(infile)) == EOF) break; + buffer[i] = c; textcount++; + } + bufferend = i; r = N - F; s = 0; + while (r < bufferend) { + f1 = (F <= bufferend - r) ? F : bufferend - r; + x = 0; y = 1; c = buffer[r]; + for (i = r - 1; i >= s; i--) + if (buffer[i] == c) { + for (j = 1; j < f1; j++) + if (buffer[i + j] != buffer[r + j]) break; + if (j > y) { + x = i; y = j; + } + } + if (y <= P) { y = 1; output1(c); } + else output2(x & (N - 1), y - 2); + r += y; s += y; + if (r >= N * 2 - F) { + for (i = 0; i < N; i++) buffer[i] = buffer[i + N]; + bufferend -= N; r -= N; s -= N; + while (bufferend < N * 2) { + if ((c = fgetc(infile)) == EOF) break; + buffer[bufferend++] = c; textcount++; + } + } + } + flush_bit_buffer(); + printf("text: %ld bytes\n", textcount); + printf("code: %ld bytes (%ld%%)\n", + codecount, (codecount * 100) / textcount); +} + +int getbit(int n) /* get n bits */ +{ + int i, x; + static int buf, mask = 0; + + x = 0; + for (i = 0; i < n; i++) { + if (mask == 0) { + if ((buf = fgetc(infile)) == EOF) return EOF; + mask = 128; + } + x <<= 1; + if (buf & mask) x++; + mask >>= 1; + } + return x; +} + +void decode(void) +{ + int i, j, k, r, c; + + for (i = 0; i < N - F; i++) buffer[i] = ' '; + r = N - F; + while ((c = getbit(1)) != EOF) { + if (c) { + if ((c = getbit(8)) == EOF) break; + fputc(c, outfile); + buffer[r++] = c; r &= (N - 1); + } else { + if ((i = getbit(EI)) == EOF) break; + if ((j = getbit(EJ)) == EOF) break; + for (k = 0; k <= j + 1; k++) { + c = buffer[(i + k) & (N - 1)]; + fputc(c, outfile); + buffer[r++] = c; r &= (N - 1); + } + } + } +} + +int main(int argc, char *argv[]) +{ + int enc; + char *s; + + if (argc != 4) { + printf("Usage: lzss e/d infile outfile\n\te = encode\td = decode\n"); + return 1; + } + s = argv[1]; + if (s[1] == 0 && (*s == 'd' || *s == 'D' || *s == 'e' || *s == 'E')) + enc = (*s == 'e' || *s == 'E'); + else { + printf("? %s\n", s); return 1; + } + if ((infile = fopen(argv[2], "rb")) == NULL) { + printf("? %s\n", argv[2]); return 1; + } + if ((outfile = fopen(argv[3], "wb")) == NULL) { + printf("? %s\n", argv[3]); return 1; + } + if (enc) encode(); else decode(); + fclose(infile); fclose(outfile); + return 0; +} + |