aboutsummaryrefslogtreecommitdiffstats
path: root/icecompr/iceuncompr.c
diff options
context:
space:
mode:
Diffstat (limited to 'icecompr/iceuncompr.c')
-rw-r--r--icecompr/iceuncompr.c162
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();
+}
+