add "best" and "worst" compression modes

This commit is contained in:
Connor Olding 2018-08-10 05:51:50 +02:00
parent 0423c2f701
commit dd61083334
1 changed files with 12 additions and 8 deletions

20
fs.py
View File

@ -40,7 +40,7 @@ def hexdump(data):
print(("{:06X} |" + " {:02X}" * len(butts)).format(i * 16, *butts)) print(("{:06X} |" + " {:02X}" * len(butts)).format(i * 16, *butts))
def compress(data, mode="greedy"): def compress(data, mode="greedy"):
assert mode == "greedy", f"unknown mode: {mode}" assert mode in "worst greedy best".split(), f"unknown mode: {mode}"
comp = bytearray() comp = bytearray()
comp.extend(W4(len(data))) comp.extend(W4(len(data)))
@ -54,9 +54,9 @@ def compress(data, mode="greedy"):
max_len = 0x3F + 3 max_len = 0x3F + 3
def find_match(sub): def find_match(sub):
if len(sub) < min_len: if mode == "worst" or len(sub) < min_len:
return None, None return None, None
match_i, match_len = None, None best_i, best_len = None, None
for i in range(buf_len): for i in range(buf_len):
match_i, match_len = (buf_i - i) % buf_len, 0 match_i, match_len = (buf_i - i) % buf_len, 0
@ -71,12 +71,16 @@ def compress(data, mode="greedy"):
break break
if match_len < min_len: if match_len < min_len:
match_i, match_len = None, None match_i, match_len = None, None
else: continue
if best_len is None or match_len > best_len:
best_i = match_i
best_len = match_len
if mode == "greedy":
break break
if match_len is not None: if best_len is not None:
assert min_len <= match_len <= max_len assert min_len <= best_len <= max_len
return match_i, match_len return best_i, best_len
shift = 0 shift = 0
shifted = 0 shifted = 0
@ -260,7 +264,7 @@ def create_rom(d):
if fi == 0 and di != 14 or di == 14 and fi in skip_14: if fi == 0 and di != 14 or di == 14 and fi in skip_14:
new_data = data new_data = data
else: else:
new_data = compress(data) new_data = compress(data, "best" if di == 14 else "greedy")
fmt = "compressed {:02}-{:03}.bin from {} bytes into {} ({:.2%})" fmt = "compressed {:02}-{:03}.bin from {} bytes into {} ({:.2%})"
percent = len(new_data) / len(data) if len(data) > 0 else 1 percent = len(new_data) / len(data) if len(data) > 0 else 1
print(fmt.format(di, fi, len(data), len(new_data), percent)) print(fmt.format(di, fi, len(data), len(new_data), percent))