diff options
Diffstat (limited to 'icecompr/iceuncompr.c')
-rw-r--r-- | icecompr/iceuncompr.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/icecompr/iceuncompr.c b/icecompr/iceuncompr.c new file mode 100644 index 0000000..04e7dc8 --- /dev/null +++ b/icecompr/iceuncompr.c @@ -0,0 +1,162 @@ +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +FILE *input_file; +FILE *output_file; + +int read_bitcounter; +int read_buffer; + +int write_bitcounter; +int write_buffer; + +static int read_bit() +{ + if (read_bitcounter == 0) { + read_bitcounter = 8; + read_buffer = fgetc(input_file); + } + + read_bitcounter--; + return (read_buffer >> read_bitcounter) & 1; +} + +static void write_bit(int value) +{ + write_bitcounter--; + + if (value) + write_buffer |= 1 << write_bitcounter; + + if (write_bitcounter == 0) { + fputc(write_buffer, output_file); + write_bitcounter = 8; + write_buffer = 0; + } +} + +static int read_int(int bits) +{ + int ret = 0; + while (bits-- > 0) + if (read_bit()) + ret |= 1 << bits; + return ret; +} + +static void write_zeros(int bits) +{ + while (bits-- > 0) + write_bit(0); +} + +int ice_uncompress() +{ + read_bitcounter = 0; + read_buffer = 0; + + write_bitcounter = 8; + write_buffer = 0; + + int magic1_ok = read_int(32) == 0x49434543; + int magic2_ok = read_int(32) == 0x4f4d5052; + + if (!magic1_ok || !magic2_ok) { + fprintf(stderr, "Missing ICECOMPR magic. Abort!\n"); + return 1; + } + + while (1) + { + if (read_bit()) { + write_zeros(read_int(2)); + write_bit(1); + } else + if (read_bit()) { + write_zeros(read_int(5)); + write_bit(1); + } else + if (read_bit()) { + write_zeros(read_int(8)); + write_bit(1); + } else + if (read_bit()) { + int n = read_int(6); + while (n--) + write_bit(read_bit()); + write_bit(1); + } else + if (read_bit()) { + write_zeros(read_int(23)); + write_bit(1); + } else { + write_zeros(read_int(23)); + break; + } + } + + return 0; +} + +void help() +{ + printf("\n"); + printf("Usage: iceuncompr [input-file [output-file]]\n"); + printf("\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + input_file = stdin; + output_file = stdout; + + int opt; + while ((opt = getopt(argc, argv, "v")) != -1) + { + switch (opt) + { + case 'v': + break; + default: + help(); + } + } + + if (optind < argc) { + input_file = fopen(argv[optind], "rb"); + if (input_file == NULL) { + fprintf(stderr, "Failed to open input file `%s': %s\n", argv[optind], strerror(errno)); + return 1; + } + optind++; + } + + if (optind < argc) { + output_file = fopen(argv[optind], "wb"); + if (output_file == NULL) { + fprintf(stderr, "Failed to open output file `%s': %s\n", argv[optind], strerror(errno)); + return 1; + } + optind++; + } + + if (optind != argc) + help(); + + if (optind != argc) + help(); + + return ice_uncompress(); +} + |