From ca95febc1cd6c227f59ca9ab143f4779b4665c12 Mon Sep 17 00:00:00 2001 From: Andrew Cook Date: Wed, 8 Mar 2023 14:04:35 +1100 Subject: [PATCH] Raise minimum count for iterate to 2 alternate to 3 Sligly saves space but mostly removes overlapping encodings --- home/decompress.asm | 4 +--- tools/lz/dpcomp.c | 6 ++++-- tools/lz/output.c | 8 ++++++-- tools/lz/proto.h | 1 + tools/lz/uncomp.c | 2 +- tools/lz/util.c | 13 ++++++++++++- 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/home/decompress.asm b/home/decompress.asm index f426d669a0..65026a3a6a 100644 --- a/home/decompress.asm +++ b/home/decompress.asm @@ -170,9 +170,6 @@ DEF LZ_LONG_HI EQU %00000011 ld [hli], a pop de - ; assume count >= 3, because < 3 is nonsense - dec bc - dec bc jr .lz_copy_repeat .lz_copy @@ -288,6 +285,7 @@ DEF LZ_LONG_HI EQU %00000011 .lz_iterate ld a, [de] + ld [hli], a inc de jr .fill diff --git a/tools/lz/dpcomp.c b/tools/lz/dpcomp.c index 19d904ff66..42338a7f3f 100644 --- a/tools/lz/dpcomp.c +++ b/tools/lz/dpcomp.c @@ -67,7 +67,8 @@ void process_input(void) { unsigned count = 0; do { count++; - consider(plen, (struct command) { + if (!current_byte || count >= 2) + consider(plen, (struct command) { .command = current_byte ? LZ_REPEAT : LZ_ZERO, .count = count, .value = current_byte, @@ -78,7 +79,8 @@ void process_input(void) { count = 1; do { count++; - consider(plen, (struct command) { + if (count >= 3) + consider(plen, (struct command) { .command = LZ_ALTERNATE, .count = count, .value = (data[plen - count + 1] << 8) | (data[plen - count]), diff --git a/tools/lz/output.c b/tools/lz/output.c index 053a5dce64..2137b26bf7 100644 --- a/tools/lz/output.c +++ b/tools/lz/output.c @@ -101,11 +101,15 @@ void write_commands_to_file (const char * file, const struct command * commands, } void write_command_to_file (FILE * fp, struct command command, const unsigned char * input_stream) { - if ((!command.count) || (command.count > MAX_COMMAND_COUNT)) error_exit(2, "invalid command in output stream"); unsigned char buf[4]; unsigned char * pos = buf; int n; - command.count --; + + command.count -= minimum_count(command.command); + + /* Check for over and under sized commands */ + if (command.count > MAX_COMMAND_COUNT - 1) error_exit(2, "invalid command in output stream"); + if (command.count < SHORT_COMMAND_COUNT) *(pos ++) = (command.command << 5) + command.count; else { diff --git a/tools/lz/proto.h b/tools/lz/proto.h index b31fdd45ba..c5b2d5e307 100644 --- a/tools/lz/proto.h +++ b/tools/lz/proto.h @@ -66,6 +66,7 @@ unsigned char * get_uncompressed_data(const struct command *, const unsigned cha // util.c noreturn error_exit(int, const char *, ...); unsigned char * read_file_into_buffer(const char *, unsigned short *); +unsigned minimum_count(unsigned command); short command_size(struct command); unsigned short compressed_length(const struct command *, unsigned short); diff --git a/tools/lz/uncomp.c b/tools/lz/uncomp.c index 0e5b078ed6..c4595b3512 100644 --- a/tools/lz/uncomp.c +++ b/tools/lz/uncomp.c @@ -20,7 +20,7 @@ struct command * get_commands_from_file (const unsigned char * data, unsigned sh if (!(remaining --)) goto error; current -> count |= *(rp ++); } - current -> count ++; + current -> count += minimum_count(current -> command); switch (current -> command) { case LZ_DATA: if (remaining <= current -> count) goto error; diff --git a/tools/lz/util.c b/tools/lz/util.c index 57f280902e..c7443fc41e 100644 --- a/tools/lz/util.c +++ b/tools/lz/util.c @@ -22,8 +22,19 @@ unsigned char * read_file_into_buffer (const char * file, unsigned short * size) return buf; } +unsigned minimum_count (unsigned command) { + switch (command) { + case LZ_ALTERNATE: + return 3; + case LZ_REPEAT: + return 2; + default: + return 1; + } +} + short command_size (struct command command) { - short header_size = 1 + (command.count > SHORT_COMMAND_COUNT); + short header_size = 1 + (command.count - minimum_count(command.command) > SHORT_COMMAND_COUNT - 1); if (command.command & 4) return header_size + 1 + (command.value >= 0); return header_size + command.command[(short []) {command.count, 1, 2, 0}]; }