diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lz/main.c | 11 | ||||
-rw-r--r-- | tools/lz/merging.c | 43 | ||||
-rw-r--r-- | tools/lz/nullcomp.c | 2 | ||||
-rw-r--r-- | tools/lz/output.c | 12 | ||||
-rw-r--r-- | tools/lz/packing.c | 5 | ||||
-rw-r--r-- | tools/lz/proto.h | 4 | ||||
-rw-r--r-- | tools/lz/repcomp.c | 2 | ||||
-rw-r--r-- | tools/lz/spcomp.c | 6 | ||||
-rw-r--r-- | tools/lz/uncomp.c | 4 |
9 files changed, 70 insertions, 19 deletions
diff --git a/tools/lz/main.c b/tools/lz/main.c index 428a027f..62e6dc41 100644 --- a/tools/lz/main.c +++ b/tools/lz/main.c @@ -37,13 +37,16 @@ struct command * compress (const unsigned char * data, unsigned short * size, un } else { struct command * compressed_sequences[COMPRESSION_METHODS]; unsigned short lengths[COMPRESSION_METHODS]; - unsigned flags = compressor -> methods; + unsigned flags = 0; for (current = 0; current < COMPRESSION_METHODS; current ++) { lengths[current] = *size; - if (!flags) flags = (++ compressor) -> methods; - compressed_sequences[current] = compressor -> function(data, bitflipped, lengths + current, -- flags); + if (flags == compressor -> methods) { + flags = 0; + compressor ++; + } + compressed_sequences[current] = compressor -> function(data, bitflipped, lengths + current, flags ++); } - result = select_command_sequence(compressed_sequences, lengths, COMPRESSION_METHODS, size); + result = select_optimal_sequence(compressed_sequences, lengths, size); for (current = 0; current < COMPRESSION_METHODS; current ++) free(compressed_sequences[current]); } free(bitflipped); diff --git a/tools/lz/merging.c b/tools/lz/merging.c index def572b1..79abb6d2 100644 --- a/tools/lz/merging.c +++ b/tools/lz/merging.c @@ -1,8 +1,47 @@ #include "proto.h" -struct command * select_command_sequence (struct command ** sequences, const unsigned short * lengths, unsigned count, unsigned short * final_length) { +struct command * select_optimal_sequence (struct command ** sequences, const unsigned short * lengths, unsigned short * final_length) { + struct command * compressor_sequences[NUM_COMPRESSORS * 2]; + unsigned short compressor_lengths[NUM_COMPRESSORS * 2]; + struct command * inverted_sequences[COMPRESSION_METHODS]; + unsigned short inverted_lengths[COMPRESSION_METHODS]; + unsigned p, current, method = 0; + for (current = 0; current < NUM_COMPRESSORS; current ++) { + compressor_sequences[current] = select_command_sequence(sequences + method, lengths + method, compressors[current].methods, compressor_lengths + current); + compressor_sequences[current + NUM_COMPRESSORS] = select_command_sequence(sequences + method, lengths + method, -(int) compressors[current].methods, + compressor_lengths + (current + NUM_COMPRESSORS)); + for (p = 0; p < compressors[current].methods; p ++) { + inverted_sequences[method + compressors[current].methods - 1 - p] = sequences[method + p]; + inverted_lengths[method + compressors[current].methods - 1 - p] = lengths[method + p]; + } + method += compressors[current].methods; + } + unsigned short final_lengths[8]; + struct command * final_sequences[8] = { + select_command_sequence(compressor_sequences, compressor_lengths, NUM_COMPRESSORS, final_lengths), + select_command_sequence(compressor_sequences, compressor_lengths, -NUM_COMPRESSORS, final_lengths + 1), + select_command_sequence(compressor_sequences + NUM_COMPRESSORS, compressor_lengths + NUM_COMPRESSORS, NUM_COMPRESSORS, final_lengths + 2), + select_command_sequence(compressor_sequences + NUM_COMPRESSORS, compressor_lengths + NUM_COMPRESSORS, -NUM_COMPRESSORS, final_lengths + 3), + select_command_sequence(sequences, lengths, COMPRESSION_METHODS, final_lengths + 4), + select_command_sequence(sequences, lengths, -COMPRESSION_METHODS, final_lengths + 5), + select_command_sequence(inverted_sequences, inverted_lengths, COMPRESSION_METHODS, final_lengths + 6), + select_command_sequence(inverted_sequences, inverted_lengths, -COMPRESSION_METHODS, final_lengths + 7) + }; + for (current = 0; current < (2 * NUM_COMPRESSORS); current ++) free(compressor_sequences[current]); + struct command * result = select_command_sequence(final_sequences, final_lengths, 8, final_length); + for (current = 0; current < 8; current ++) free(final_sequences[current]); + return result; +} + +struct command * select_command_sequence (struct command ** sequences, const unsigned short * lengths, int count, unsigned short * final_length) { + // negative count indicates iterating backwards unsigned short min_sequence = 0, min_length = compressed_length(*sequences, *lengths); unsigned short seq, len; + int backwards = 0; + if (count < 0) { + backwards = 1; + count = -count; + } for (seq = 1; seq < count; seq ++) { len = compressed_length(sequences[seq], lengths[seq]); if (len < min_length) { @@ -15,7 +54,9 @@ struct command * select_command_sequence (struct command ** sequences, const uns memcpy(current, sequences[min_sequence], *final_length * sizeof(struct command)); struct command * new; for (seq = 1; seq < count; seq ++) { + if (backwards) seq = count - seq; new = merge_command_sequences(current, *final_length, sequences[(seq + min_sequence) % count], lengths[(seq + min_sequence) % count], final_length); + if (backwards) seq = count - seq; // restore the value for the loop free(current); current = new; } diff --git a/tools/lz/nullcomp.c b/tools/lz/nullcomp.c index d4535bd3..33d0b726 100644 --- a/tools/lz/nullcomp.c +++ b/tools/lz/nullcomp.c @@ -6,7 +6,7 @@ Flags values: 0 = split a trailing 33-to-64-byte block at the end into two short blocks; 1 = don't */ -struct command * store_uncompressed (__attribute__((unused)) const unsigned char * data, __attribute__((unused)) const unsigned char * bitflipped, unsigned short * size, unsigned flags) { +struct command * store_uncompressed (const unsigned char * data, const unsigned char * bitflipped, unsigned short * size, unsigned flags) { unsigned short position, block, remainder = *size; struct command * result = NULL; *size = 0; diff --git a/tools/lz/output.c b/tools/lz/output.c index 43e7ba92..484a9516 100644 --- a/tools/lz/output.c +++ b/tools/lz/output.c @@ -28,8 +28,16 @@ void write_commands_and_padding_to_textfile (const char * file, const struct com if (fputs("\tlzend\n", fp) < 0) error_exit(1, "could not write terminator to compressed output"); if (padding_size) { input_stream += padding_offset; - int rv = fprintf(fp, "\tdb $%02hhx", *(input_stream ++)); - while ((rv >= 0) && (-- padding_size)) rv = fprintf(fp, ", $%02hhx", *(input_stream ++)); + int rv = 0; + unsigned pos; + const char * prefix = "\tdb"; + for (pos = 0; (rv >= 0) && (pos < padding_size); pos ++) { + if (input_stream[pos]) + rv = fprintf(fp, "%s $%02hhx", prefix, input_stream[pos]); + else + rv = fprintf(fp, "%s 0", prefix); + prefix = ","; + } if (rv >= 0) rv = -(putc('\n', fp) == EOF); if (rv < 0) error_exit(1, "could not write padding to compressed output"); } diff --git a/tools/lz/packing.c b/tools/lz/packing.c index b3e64634..3623be96 100644 --- a/tools/lz/packing.c +++ b/tools/lz/packing.c @@ -17,7 +17,7 @@ void optimize (struct command * commands, unsigned short count) { next -> command = 7; continue; } - if (next -> command == commands -> command) { + if (next -> command == commands -> command) switch (commands -> command) { case 0: if ((commands -> value + commands -> count) != next -> value) break; @@ -31,7 +31,6 @@ void optimize (struct command * commands, unsigned short count) { break; case 1: if (commands -> value != next -> value) break; - // fallthrough case 3: if ((commands -> count + next -> count) <= MAX_COMMAND_COUNT) { commands -> count += next -> count; @@ -40,9 +39,7 @@ void optimize (struct command * commands, unsigned short count) { } next -> count = (commands -> count + next -> count) - MAX_COMMAND_COUNT; commands -> count = MAX_COMMAND_COUNT; - break; } - } commands = next; } } diff --git a/tools/lz/proto.h b/tools/lz/proto.h index 3ca98715..84577422 100644 --- a/tools/lz/proto.h +++ b/tools/lz/proto.h @@ -3,6 +3,7 @@ #include <string.h> #include <stdarg.h> +#define NUM_COMPRESSORS 4 #define COMPRESSION_METHODS 96 /* sum of all values for the methods field in compressors */ #define MAX_FILE_SIZE 32768 #define SHORT_COMMAND_COUNT 32 @@ -48,7 +49,8 @@ int main(int, char **); struct command * compress(const unsigned char *, unsigned short *, unsigned); // merging.c -struct command * select_command_sequence(struct command **, const unsigned short *, unsigned, unsigned short *); +struct command * select_optimal_sequence(struct command **, const unsigned short *, unsigned short *); +struct command * select_command_sequence(struct command **, const unsigned short *, int, unsigned short *); struct command * merge_command_sequences(const struct command *, unsigned short, const struct command *, unsigned short, unsigned short *); // mpcomp.c diff --git a/tools/lz/repcomp.c b/tools/lz/repcomp.c index f2bbad8a..754529e8 100644 --- a/tools/lz/repcomp.c +++ b/tools/lz/repcomp.c @@ -7,7 +7,7 @@ (lowest bit to highest: repeat single byte (1), repeat two bytes (2), repeat zeros (3)). */ -struct command * try_compress_repetitions (const unsigned char * data, __attribute__((unused)) const unsigned char * bitflipped, unsigned short * size, unsigned flags) { +struct command * try_compress_repetitions (const unsigned char * data, const unsigned char * bitflipped, unsigned short * size, unsigned flags) { unsigned short pos = 0, skipped = 0; struct command * result = malloc(*size * sizeof(struct command)); struct command * current = result; diff --git a/tools/lz/spcomp.c b/tools/lz/spcomp.c index b6184836..ab33dbbc 100644 --- a/tools/lz/spcomp.c +++ b/tools/lz/spcomp.c @@ -62,11 +62,11 @@ struct command find_best_copy (const unsigned char * data, unsigned short positi struct command simple = {.command = 7}; struct command flipped = simple, backwards = simple; short count, offset; - if ((count = scan_forwards(data + position, length - position, data, position, &offset))) + if (count = scan_forwards(data + position, length - position, data, position, &offset)) simple = (struct command) {.command = 4, .count = count, .value = offset}; - if ((count = scan_forwards(data + position, length - position, bitflipped, position, &offset))) + if (count = scan_forwards(data + position, length - position, bitflipped, position, &offset)) flipped = (struct command) {.command = 5, .count = count, .value = offset}; - if ((count = scan_backwards(data, length - position, position, &offset))) + if (count = scan_backwards(data, length - position, position, &offset)) backwards = (struct command) {.command = 6, .count = count, .value = offset}; struct command command; switch (flags / 24) { diff --git a/tools/lz/uncomp.c b/tools/lz/uncomp.c index 3544cd93..b22fc75f 100644 --- a/tools/lz/uncomp.c +++ b/tools/lz/uncomp.c @@ -49,7 +49,7 @@ struct command * get_commands_from_file (const unsigned char * data, unsigned sh } if (slack) *slack = *size - (rp - data); *size = current - result; - return realloc(result, *size * sizeof(struct command)); + return realloc(result, (*size ? *size : 1) * sizeof(struct command)); error: free(result); return NULL; @@ -88,5 +88,5 @@ unsigned char * get_uncompressed_data (const struct command * commands, const un } } *size = current - result; - return result; + return realloc(result, *size ? *size : 1); } |